From 78fec5a735dba902d1ec6544d57eaf40967925c8 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Tue, 22 Oct 2024 14:29:08 -0700 Subject: [PATCH 01/16] Execute net tools plugins --- .../NuGet.Protocol/Plugins/IPluginFactory.cs | 7 ++ .../NuGet.Protocol/Plugins/PluginFactory.cs | 114 ++++++++++++++---- .../PublicAPI/net472/PublicAPI.Unshipped.txt | 2 + .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 2 + .../netstandard2.0/PublicAPI.Unshipped.txt | 2 + .../Plugins/PluginFactoryTests.cs | 97 +++++++++++++++ 6 files changed, 199 insertions(+), 25 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs index ae187ee4f9f..2053acdbe94 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs @@ -42,5 +42,12 @@ Task GetOrCreateAsync( IRequestHandlers requestHandlers, ConnectionOptions options, CancellationToken sessionCancellationToken); + + Task GetOrCreateNetToolsPluginAsync( + string filePath, + IEnumerable arguments, + IRequestHandlers requestHandlers, + ConnectionOptions options, + CancellationToken sessionCancellationToken); } } diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs index 2b2e6b44a01..eebe5123441 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs @@ -136,7 +136,7 @@ public async Task GetOrCreateAsync( var lazyTask = _plugins.GetOrAdd( filePath, (path) => new Lazy>( - () => CreatePluginAsync(filePath, arguments, requestHandlers, options, sessionCancellationToken))); + () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isDotnetTools: false, sessionCancellationToken))); await lazyTask.Value; @@ -149,36 +149,60 @@ private async Task CreatePluginAsync( IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, + bool isDotnetTools, CancellationToken sessionCancellationToken) { var args = string.Join(" ", arguments); -#if IS_DESKTOP - var startInfo = new ProcessStartInfo(filePath) + + ProcessStartInfo startInfo; + + if (!isDotnetTools) { - Arguments = args, - UseShellExecute = false, - RedirectStandardError = false, - RedirectStandardInput = true, - RedirectStandardOutput = true, - StandardOutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), - WindowStyle = ProcessWindowStyle.Hidden, - }; +#if IS_DESKTOP + startInfo = new ProcessStartInfo(filePath) + { + Arguments = args, + UseShellExecute = false, + RedirectStandardError = false, + RedirectStandardInput = true, + RedirectStandardOutput = true, + StandardOutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), + WindowStyle = ProcessWindowStyle.Hidden, + }; #else - var startInfo = new ProcessStartInfo - { - FileName = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? - (NuGet.Common.RuntimeEnvironmentHelper.IsWindows ? - "dotnet.exe" : - "dotnet"), - Arguments = $"\"{filePath}\" " + args, - UseShellExecute = false, - RedirectStandardError = false, - RedirectStandardInput = true, - RedirectStandardOutput = true, - StandardOutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), - WindowStyle = ProcessWindowStyle.Hidden, - }; + startInfo = new ProcessStartInfo + { + FileName = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? + (NuGet.Common.RuntimeEnvironmentHelper.IsWindows ? + "dotnet.exe" : + "dotnet"), + Arguments = $"\"{filePath}\" " + args, + UseShellExecute = false, + RedirectStandardError = false, + RedirectStandardInput = true, + RedirectStandardOutput = true, + StandardOutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), + WindowStyle = ProcessWindowStyle.Hidden, + }; #endif + } + else + { + // A dotnet tools plugin. Execute it directly. + + startInfo = new ProcessStartInfo(filePath) + { + FileName = filePath, + Arguments = args, + UseShellExecute = false, + RedirectStandardError = false, + RedirectStandardInput = true, + RedirectStandardOutput = true, + StandardOutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), + WindowStyle = ProcessWindowStyle.Hidden, + }; + } + var pluginProcess = new PluginProcess(startInfo); string pluginId = Plugin.CreateNewId(); @@ -455,5 +479,45 @@ private static void WriteCommonLogMessages(IPluginLogger logger) logger.Write(new ProcessLogMessage(logger.Now)); logger.Write(new ThreadPoolLogMessage(logger.Now)); } + + public async Task GetOrCreateNetToolsPluginAsync(string filePath, IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, CancellationToken sessionCancellationToken) + { + if (_isDisposed) + { + throw new ObjectDisposedException(nameof(PluginFactory)); + } + + if (string.IsNullOrEmpty(filePath)) + { + throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(filePath)); + } + + if (arguments == null) + { + throw new ArgumentNullException(nameof(arguments)); + } + + if (requestHandlers == null) + { + throw new ArgumentNullException(nameof(requestHandlers)); + } + + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + sessionCancellationToken.ThrowIfCancellationRequested(); + + var lazyTask = _plugins.GetOrAdd( + filePath, + (path) => new Lazy>( + () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isDotnetTools: true, sessionCancellationToken))); + + await lazyTask.Value; + + // Manage plugin lifetime by its idleness. Thus, don't allow callers to prematurely dispose of a plugin. + return new NoOpDisposePlugin(lazyTask.Value.Result); + } } } diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt index 7e98009cd58..d48329d4256 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,2 +1,4 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt index 7e98009cd58..d48329d4256 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -1,2 +1,4 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 7e98009cd58..d48329d4256 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,2 +1,4 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs index 4b560bf1acb..e1b10474044 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs @@ -2,8 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.IO; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using NuGet.Test.Utility; using Xunit; namespace NuGet.Protocol.Plugins.Tests @@ -135,6 +138,100 @@ public async Task GetOrCreateAsync_ThrowsIfDisposed() Assert.Equal(nameof(PluginFactory), exception.ObjectName); } + [PlatformFact(Platform.Windows)] + public async Task GetOrCreateNetPluginAsync_CreatesPluginAndSendsHandshakeRequest() + { + using TestDirectory testDirectory = TestDirectory.Create(); + string pluginPath = Path.Combine(testDirectory.Path, "nuget-plugin-batFile.bat"); + + string outputFilePath = Path.Combine(testDirectory.Path, "output.txt"); + File.WriteAllText(outputFilePath, ""); + + // Create the .bat file that simulates a plugin + // Simply waits for a json request that looks like`{"RequestId":"ff52f0ae-28c9-4a19-957d-78db5b68f3f2","Type":"Request","Method":"Handshake","Payload":{"ProtocolVersion":"2.0.0","MinimumProtocolVersion":"1.0.0"}} ` + // and sends it back with the type changed to `Response` + string batFileContent = $@" +@echo off +setlocal enabledelayedexpansion + +set outputFile={outputFilePath} + +:: Clear the output file initially (if it exists) +echo. > %outputFile% + +:: Initialize the counter for '}}' characters +set closingBraceCount=0 + +:loop + +:: Read from stdin (standard input) +set /p input="""" + +:: Count occurrences of '}}' in the input +for /l %%i in (0,1,1023) do ( + if ""!input:~%%i,1!""==""}}"" ( + set /a closingBraceCount+=1 + ) +) + +:: Write the input to the output file +echo !input! >> %outputFile% + +:: If '}}' has appeared twice (even across multiple inputs), process the output file +if !closingBraceCount! geq 2 ( + goto processOutput +) + +:: Go back to the loop to accept more input +goto loop + +:processOutput + +for /f ""delims="" %%a in (%outputFile%) do ( + set ""singleLine=!singleLine! %%a"" +) + +:: Perform string replacement (""Request"" -> ""Response"") in the single line +set modifiedLine=!singleLine:""Type"":""Request""=""Type"":""Response""! + +echo !modifiedLine! +"; + File.WriteAllText(pluginPath, batFileContent); + + var args = PluginConstants.PluginArguments; + var reqHandler = new RequestHandlers(); + var options = ConnectionOptions.CreateDefault(); + + var pluginFactory = new PluginFactory(Timeout.InfiniteTimeSpan); + + // Act + var plugin = Assert.ThrowsAsync(() => pluginFactory.GetOrCreateNetToolsPluginAsync(pluginPath, args, reqHandler, options, CancellationToken.None)); + await Task.Delay(10); + + // Assert + Assert.NotNull(plugin); + string jsonOutput = File.ReadAllText(outputFilePath); + var jsonDocument = JsonDocument.Parse(jsonOutput); + var rootElement = jsonDocument.RootElement; + if (rootElement.TryGetProperty("Method", out JsonElement methodElement)) + { + Assert.Equal("Handshake", methodElement.GetString()); + } + else + { + Assert.Fail("The Method property was not found in the JSON output."); + } + + if (rootElement.TryGetProperty("Type", out JsonElement typeElement)) + { + Assert.Equal("Request", typeElement.GetString()); + } + else + { + Assert.Fail("The Type property was not found in the JSON output."); + } + } + [Fact] public async Task CreateFromCurrentProcessAsync_ThrowsForNullRequestHandlers() { From 0f0e5af8246db8c2533216805336d8ae32bf9bfd Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Tue, 22 Oct 2024 15:53:18 -0700 Subject: [PATCH 02/16] Remove suppression --- src/NuGet.Core/NuGet.Protocol/GlobalSuppressions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NuGet.Core/NuGet.Protocol/GlobalSuppressions.cs b/src/NuGet.Core/NuGet.Protocol/GlobalSuppressions.cs index fbb29505816..c8e0b1cab94 100644 --- a/src/NuGet.Core/NuGet.Protocol/GlobalSuppressions.cs +++ b/src/NuGet.Core/NuGet.Protocol/GlobalSuppressions.cs @@ -133,7 +133,6 @@ [assembly: SuppressMessage("Build", "CA1031:Modify 'FireBeforeClose' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.Protocol.Plugins.Plugin.FireBeforeClose")] [assembly: SuppressMessage("Build", "CA1031:Modify 'FireClosed' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.Protocol.Plugins.Plugin.FireClosed")] [assembly: SuppressMessage("Build", "CA2000:Call System.IDisposable.Dispose on object created by 'new MonitorNuGetProcessExitRequestHandler(plugin)' before all references to it are out of scope.", Justification = "", Scope = "member", Target = "~M:NuGet.Protocol.Plugins.PluginFactory.CreateFromCurrentProcessAsync(NuGet.Protocol.Plugins.IRequestHandlers,NuGet.Protocol.Plugins.ConnectionOptions,System.Threading.CancellationToken)~System.Threading.Tasks.Task{NuGet.Protocol.Plugins.IPlugin}")] -[assembly: SuppressMessage("Build", "CA2000:Use recommended dispose pattern to ensure that object created by 'new PluginProcess(startInfo)' is disposed on all paths. If possible, wrap the creation within a 'using' statement or a 'using' declaration. Otherwise, use a try-finally pattern, with a dedicated local variable declared before the try region and an unconditional Dispose invocation on non-null value in the 'finally' region, say 'x?.Dispose()'. If the object is explicitly disposed within the try region or the dispose ownership is transfered to another object or method, assign 'null' to the local variable just after such an operation to prevent double dispose in 'finally'.", Justification = "The responsibility to dispose the object is transferred to another object or wrapper that's created in the method and returned to the caller", Scope = "member", Target = "~M:NuGet.Protocol.Plugins.PluginFactory.CreatePluginAsync(System.String,System.Collections.Generic.IEnumerable{System.String},NuGet.Protocol.Plugins.IRequestHandlers,NuGet.Protocol.Plugins.ConnectionOptions,System.Threading.CancellationToken)~System.Threading.Tasks.Task{NuGet.Protocol.Plugins.IPlugin}")] [assembly: SuppressMessage("Build", "CA1031:Modify 'SendCloseRequest' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.Protocol.Plugins.PluginFactory.SendCloseRequest(NuGet.Protocol.Plugins.IPlugin)")] [assembly: SuppressMessage("Build", "CA1822:Member GetPluginOperationClaimsAsync does not access instance data and can be marked as static (Shared in VisualBasic)", Justification = "", Scope = "member", Target = "~M:NuGet.Protocol.Plugins.PluginManager.GetPluginOperationClaimsAsync(NuGet.Protocol.Plugins.IPlugin,System.String,Newtonsoft.Json.Linq.JObject,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Collections.Generic.IReadOnlyList{NuGet.Protocol.Plugins.OperationClaim}}")] [assembly: SuppressMessage("Build", "CA1031:Modify 'TryCreatePluginAsync' to catch a more specific allowed exception type, or rethrow the exception.", Justification = "", Scope = "member", Target = "~M:NuGet.Protocol.Plugins.PluginManager.TryCreatePluginAsync(NuGet.Protocol.Plugins.PluginDiscoveryResult,NuGet.Protocol.Plugins.OperationClaim,NuGet.Protocol.Plugins.PluginManager.PluginRequestKey,System.String,Newtonsoft.Json.Linq.JObject,System.Threading.CancellationToken)~System.Threading.Tasks.Task{System.Tuple{System.Boolean,NuGet.Protocol.Plugins.PluginCreationResult}}")] From 64a20078beb8c9a1f053c762a9d8acb6c6208ca3 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Thu, 24 Oct 2024 12:22:35 -0700 Subject: [PATCH 03/16] Fix test --- .../Plugins/PluginFactoryTests.cs | 148 ++++++++++-------- 1 file changed, 83 insertions(+), 65 deletions(-) diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs index e1b10474044..7ede10209c0 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs @@ -3,7 +3,6 @@ using System; using System.IO; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using NuGet.Test.Utility; @@ -144,57 +143,97 @@ public async Task GetOrCreateNetPluginAsync_CreatesPluginAndSendsHandshakeReques using TestDirectory testDirectory = TestDirectory.Create(); string pluginPath = Path.Combine(testDirectory.Path, "nuget-plugin-batFile.bat"); - string outputFilePath = Path.Combine(testDirectory.Path, "output.txt"); - File.WriteAllText(outputFilePath, ""); - // Create the .bat file that simulates a plugin // Simply waits for a json request that looks like`{"RequestId":"ff52f0ae-28c9-4a19-957d-78db5b68f3f2","Type":"Request","Method":"Handshake","Payload":{"ProtocolVersion":"2.0.0","MinimumProtocolVersion":"1.0.0"}} ` - // and sends it back with the type changed to `Response` + // It then creates a response with the same RequestId and Method, but with the Type changed to `Response` and Adds a Payload with a ResponseCode of 0 + // It finally sends a handshake request back to the caller. This completes the handshake process. string batFileContent = $@" @echo off -setlocal enabledelayedexpansion - -set outputFile={outputFilePath} - -:: Clear the output file initially (if it exists) -echo. > %outputFile% - -:: Initialize the counter for '}}' characters -set closingBraceCount=0 - -:loop - -:: Read from stdin (standard input) -set /p input="""" - -:: Count occurrences of '}}' in the input -for /l %%i in (0,1,1023) do ( - if ""!input:~%%i,1!""==""}}"" ( - set /a closingBraceCount+=1 +setlocal EnableDelayedExpansion + +:InputLoop +set /p jsonLine= + +set quote="" +set comma=, +set colon=: +set openCurlyBracket={{ +set closeCurlyBracket=}} +set key= +set value= +set dot=. +set onKeySearch=true +set onValueSearch=false +set enteredQuotes=false + +set pos=0 +:NextChar + set index=%pos% + set char=!jsonLine:~%pos%,1! + if ""!char!""=="""" goto endLoop + if %onKeySearch%==true ( + if %enteredQuotes%==true ( + if !char!==!quote! ( + set onKeySearch=false + set onValueSearch=true + set enteredQuotes=false + ) else ( + set key=!key!!char! + ) + ) else if !char!==!quote! ( + set enteredQuotes=true + ) + ) else if %onValueSearch%==true ( + if %enteredQuotes%==true ( + if !char!==!quote! ( + set onKeySearch=true + set onValueSearch=true + set enteredQuotes=false + set ""!key!=!value!"" + set value= + set /a pos=pos+1 + goto ClearKey + ) else ( + set value=!value!!char! + ) + ) else if !char!==!quote! ( + set enteredQuotes=true + ) else if !char!==!openCurlyBracket! ( + set onKeySearch=true + set onValueSearch=false + set key=!key!. + ) + ) else ( + echo neither ) -) - -:: Write the input to the output file -echo !input! >> %outputFile% + set /a pos=pos+1 + if ""!jsonLine:~%pos%,1!"" NEQ """" goto NextChar -:: If '}}' has appeared twice (even across multiple inputs), process the output file -if !closingBraceCount! geq 2 ( - goto processOutput -) - -:: Go back to the loop to accept more input -goto loop +:ClearKey + if ""!key!""=="""" ( + goto NextChar + ) + set lastChar=!key:~-1! + if !lastChar!==!dot! ( + goto NextChar + ) else ( + set key=!key:~0,-1! + goto ClearKey + ) + goto NextChar -:processOutput -for /f ""delims="" %%a in (%outputFile%) do ( - set ""singleLine=!singleLine! %%a"" +:endLoop +if ""!RequestId!"" == """" ( + goto InputLoop +) else ( + set HandshakeReponseJsonString={{""RequestId"":""!RequestId!"",""Type"":""Response"",""Method"":""Handshake"",""Payload"":{{""ProtocolVersion"":""2.0.0"",""ResponseCode"":0}}}} + set HandshakeRequestJsonString={{""RequestId"":""!RequestId!"",""Type"":""Request"",""Method"":""Handshake"",""Payload"":{{""ProtocolVersion"":""2.0.0"",""MinimumProtocolVersion"":""1.0.0""}}}} + echo !HandshakeReponseJsonString! + echo !HandshakeRequestJsonString! ) +goto InputLoop -:: Perform string replacement (""Request"" -> ""Response"") in the single line -set modifiedLine=!singleLine:""Type"":""Request""=""Type"":""Response""! - -echo !modifiedLine! "; File.WriteAllText(pluginPath, batFileContent); @@ -205,31 +244,10 @@ goto loop var pluginFactory = new PluginFactory(Timeout.InfiniteTimeSpan); // Act - var plugin = Assert.ThrowsAsync(() => pluginFactory.GetOrCreateNetToolsPluginAsync(pluginPath, args, reqHandler, options, CancellationToken.None)); - await Task.Delay(10); + var plugin = await pluginFactory.GetOrCreateNetToolsPluginAsync(pluginPath, args, reqHandler, options, CancellationToken.None); // Assert - Assert.NotNull(plugin); - string jsonOutput = File.ReadAllText(outputFilePath); - var jsonDocument = JsonDocument.Parse(jsonOutput); - var rootElement = jsonDocument.RootElement; - if (rootElement.TryGetProperty("Method", out JsonElement methodElement)) - { - Assert.Equal("Handshake", methodElement.GetString()); - } - else - { - Assert.Fail("The Method property was not found in the JSON output."); - } - - if (rootElement.TryGetProperty("Type", out JsonElement typeElement)) - { - Assert.Equal("Request", typeElement.GetString()); - } - else - { - Assert.Fail("The Type property was not found in the JSON output."); - } + Assert.NotNull(plugin.Connection); } [Fact] From a3a888bf9bb82158ab43cc2958afc883f7428f78 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Thu, 24 Oct 2024 15:24:46 -0700 Subject: [PATCH 04/16] PluginManager checks plugin type --- .../NuGet.Protocol/Plugins/PluginManager.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs index 6ff4407f862..295479c664d 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs @@ -212,12 +212,26 @@ private async Task> TryCreatePluginAsync( { if (result.PluginFile.State.Value == PluginFileState.Valid) { - var plugin = await _pluginFactory.GetOrCreateAsync( + IPlugin plugin; + + if (result.PluginFile.IsDotnetToolsPlugin) + { + plugin = await _pluginFactory.GetOrCreateNetToolsPluginAsync( + result.PluginFile.Path, + PluginConstants.PluginArguments, + new RequestHandlers(), + _connectionOptions, + cancellationToken); + } + else + { + plugin = await _pluginFactory.GetOrCreateAsync( result.PluginFile.Path, PluginConstants.PluginArguments, new RequestHandlers(), _connectionOptions, cancellationToken); + } var utilities = await PerformOneTimePluginInitializationAsync(plugin, cancellationToken); From da6cca7e95e03d5c70fc3a646b352f0d8c2132d7 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Fri, 1 Nov 2024 16:26:12 -0700 Subject: [PATCH 05/16] Simplify test --- .../NuGet.Protocol/Plugins/PluginFactory.cs | 1 - .../NuGet.Protocol/Plugins/PluginManager.cs | 20 ++-- .../Plugins/PluginFactoryTests.cs | 103 ++---------------- 3 files changed, 19 insertions(+), 105 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs index eebe5123441..3bcf53f171c 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs @@ -189,7 +189,6 @@ private async Task CreatePluginAsync( else { // A dotnet tools plugin. Execute it directly. - startInfo = new ProcessStartInfo(filePath) { FileName = filePath, diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs index 295479c664d..946a516eb2c 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs @@ -217,20 +217,20 @@ private async Task> TryCreatePluginAsync( if (result.PluginFile.IsDotnetToolsPlugin) { plugin = await _pluginFactory.GetOrCreateNetToolsPluginAsync( - result.PluginFile.Path, - PluginConstants.PluginArguments, - new RequestHandlers(), - _connectionOptions, - cancellationToken); + filePath: result.PluginFile.Path, + arguments: PluginConstants.PluginArguments, + requestHandlers: new RequestHandlers(), + options: _connectionOptions, + sessionCancellationToken: cancellationToken); } else { plugin = await _pluginFactory.GetOrCreateAsync( - result.PluginFile.Path, - PluginConstants.PluginArguments, - new RequestHandlers(), - _connectionOptions, - cancellationToken); + filePath: result.PluginFile.Path, + arguments: PluginConstants.PluginArguments, + requestHandlers: new RequestHandlers(), + options: _connectionOptions, + sessionCancellationToken: cancellationToken); } var utilities = await PerformOneTimePluginInitializationAsync(plugin, cancellationToken); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs index 7ede10209c0..9c89bba2e52 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs @@ -138,103 +138,17 @@ public async Task GetOrCreateAsync_ThrowsIfDisposed() } [PlatformFact(Platform.Windows)] - public async Task GetOrCreateNetPluginAsync_CreatesPluginAndSendsHandshakeRequest() + public async Task GetOrCreateNetPluginAsync_UsingBatchFile_CreatesPluginAndExecutes() { using TestDirectory testDirectory = TestDirectory.Create(); string pluginPath = Path.Combine(testDirectory.Path, "nuget-plugin-batFile.bat"); + string outputPath = Path.Combine(testDirectory.Path, "plugin-output.txt"); - // Create the .bat file that simulates a plugin - // Simply waits for a json request that looks like`{"RequestId":"ff52f0ae-28c9-4a19-957d-78db5b68f3f2","Type":"Request","Method":"Handshake","Payload":{"ProtocolVersion":"2.0.0","MinimumProtocolVersion":"1.0.0"}} ` - // It then creates a response with the same RequestId and Method, but with the Type changed to `Response` and Adds a Payload with a ResponseCode of 0 - // It finally sends a handshake request back to the caller. This completes the handshake process. string batFileContent = $@" -@echo off -setlocal EnableDelayedExpansion - -:InputLoop -set /p jsonLine= - -set quote="" -set comma=, -set colon=: -set openCurlyBracket={{ -set closeCurlyBracket=}} -set key= -set value= -set dot=. -set onKeySearch=true -set onValueSearch=false -set enteredQuotes=false - -set pos=0 -:NextChar - set index=%pos% - set char=!jsonLine:~%pos%,1! - if ""!char!""=="""" goto endLoop - if %onKeySearch%==true ( - if %enteredQuotes%==true ( - if !char!==!quote! ( - set onKeySearch=false - set onValueSearch=true - set enteredQuotes=false - ) else ( - set key=!key!!char! - ) - ) else if !char!==!quote! ( - set enteredQuotes=true - ) - ) else if %onValueSearch%==true ( - if %enteredQuotes%==true ( - if !char!==!quote! ( - set onKeySearch=true - set onValueSearch=true - set enteredQuotes=false - set ""!key!=!value!"" - set value= - set /a pos=pos+1 - goto ClearKey - ) else ( - set value=!value!!char! - ) - ) else if !char!==!quote! ( - set enteredQuotes=true - ) else if !char!==!openCurlyBracket! ( - set onKeySearch=true - set onValueSearch=false - set key=!key!. - ) - ) else ( - echo neither - ) - set /a pos=pos+1 - if ""!jsonLine:~%pos%,1!"" NEQ """" goto NextChar - -:ClearKey - if ""!key!""=="""" ( - goto NextChar - ) - set lastChar=!key:~-1! - if !lastChar!==!dot! ( - goto NextChar - ) else ( - set key=!key:~0,-1! - goto ClearKey - ) - goto NextChar - - -:endLoop -if ""!RequestId!"" == """" ( - goto InputLoop -) else ( - set HandshakeReponseJsonString={{""RequestId"":""!RequestId!"",""Type"":""Response"",""Method"":""Handshake"",""Payload"":{{""ProtocolVersion"":""2.0.0"",""ResponseCode"":0}}}} - set HandshakeRequestJsonString={{""RequestId"":""!RequestId!"",""Type"":""Request"",""Method"":""Handshake"",""Payload"":{{""ProtocolVersion"":""2.0.0"",""MinimumProtocolVersion"":""1.0.0""}}}} - echo !HandshakeReponseJsonString! - echo !HandshakeRequestJsonString! -) -goto InputLoop - -"; + @echo off + echo File executed > ""{outputPath}"" + "; + File.WriteAllText(pluginPath, batFileContent); var args = PluginConstants.PluginArguments; @@ -244,10 +158,11 @@ goto InputLoop var pluginFactory = new PluginFactory(Timeout.InfiniteTimeSpan); // Act - var plugin = await pluginFactory.GetOrCreateNetToolsPluginAsync(pluginPath, args, reqHandler, options, CancellationToken.None); + var plugin = await Assert.ThrowsAnyAsync(() => pluginFactory.GetOrCreateNetToolsPluginAsync(pluginPath, args, reqHandler, options, CancellationToken.None)); // Assert - Assert.NotNull(plugin.Connection); + string outputContent = File.ReadAllText(outputPath); + Assert.Contains("File executed", outputContent); } [Fact] From 1d4fb03e1d07a6f3ead53389005e28134e7c932c Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Fri, 1 Nov 2024 16:51:44 -0700 Subject: [PATCH 06/16] rename variable --- .../NuGet.Protocol/Plugins/PluginDiscoverer.cs | 4 ++-- src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs | 10 +++++----- src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs | 2 +- .../Plugins/PluginDiscovererTests.cs | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs index d342827a370..a91860bed47 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs @@ -197,7 +197,7 @@ internal List GetPluginsInNuGetPluginPaths() // A DotNet tool plugin if (IsValidPluginFile(fileInfo)) { - PluginFile pluginFile = new PluginFile(fileInfo.FullName, new Lazy(() => PluginFileState.Valid), isDotnetToolsPlugin: true); + PluginFile pluginFile = new PluginFile(fileInfo.FullName, new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: true); pluginFiles.Add(pluginFile); } } @@ -260,7 +260,7 @@ private static List GetNetToolsPluginsInDirectory(string directoryPa { if (IsValidPluginFile(file)) { - PluginFile pluginFile = new PluginFile(file.FullName, new Lazy(() => PluginFileState.Valid), isDotnetToolsPlugin: true); + PluginFile pluginFile = new PluginFile(file.FullName, new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: true); pluginFiles.Add(pluginFile); } } diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs index 96c24f2c86f..965f0fd1a26 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs @@ -21,19 +21,19 @@ public sealed class PluginFile public Lazy State { get; } /// - /// Is the plugin file, a dotnet tools plugin file? + /// Indicates if the plugin file is runnable, such as an executable or a script. /// - internal bool IsDotnetToolsPlugin { get; } + internal bool IsRunnablePluginFile { get; } /// /// Instantiates a new class. /// /// The plugin's file path. /// A lazy that evaluates the plugin file state. - /// Is the plugin file, a dotnet tools plugin file? - internal PluginFile(string filePath, Lazy state, bool isDotnetToolsPlugin) : this(filePath, state) + /// Is the plugin file, a runnable plugin file? + internal PluginFile(string filePath, Lazy state, bool isRunnablePluginFile) : this(filePath, state) { - IsDotnetToolsPlugin = isDotnetToolsPlugin; + IsRunnablePluginFile = isRunnablePluginFile; } /// diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs index 946a516eb2c..40905b69ce0 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs @@ -214,7 +214,7 @@ private async Task> TryCreatePluginAsync( { IPlugin plugin; - if (result.PluginFile.IsDotnetToolsPlugin) + if (result.PluginFile.IsRunnablePluginFile) { plugin = await _pluginFactory.GetOrCreateNetToolsPluginAsync( filePath: result.PluginFile.Path, diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs index f27749db149..4210cbc1b57 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs @@ -436,7 +436,7 @@ public void GetPluginsInNuGetPluginPaths_WithNuGetPluginPathsSet_ReturnsPluginsI // Assert Assert.Single(plugins); Assert.Equal(pluginInNuGetPluginPathDirectoryFilePath, plugins[0].Path); - Assert.True(plugins[0].IsDotnetToolsPlugin); + Assert.True(plugins[0].IsRunnablePluginFile); } [PlatformFact(Platform.Windows)] @@ -480,7 +480,7 @@ public void GetPluginsInPATH_WithPATHSet_ReturnsPlugin() // Assert Assert.Single(plugins); Assert.Equal(pluginInPathDirectoryFilePath, plugins[0].Path); - Assert.True(plugins[0].IsDotnetToolsPlugin); + Assert.True(plugins[0].IsRunnablePluginFile); } [PlatformFact(Platform.Windows)] @@ -503,7 +503,7 @@ public void GetPluginsInNuGetPluginPaths_NuGetPluginPathsPointsToAFile_TreatsAsP // Assert Assert.Single(plugins); Assert.Equal(pluginFilePath, plugins[0].Path); - Assert.True(plugins[0].IsDotnetToolsPlugin); + Assert.True(plugins[0].IsRunnablePluginFile); } [PlatformFact(Platform.Windows)] @@ -525,7 +525,7 @@ public void GetPluginsInNuGetPluginPaths_NuGetPluginPathsPointsToAFileThatDoesNo // Assert Assert.Single(plugins); - Assert.False(plugins[0].IsDotnetToolsPlugin); + Assert.False(plugins[0].IsRunnablePluginFile); } [PlatformFact(Platform.Windows)] @@ -549,7 +549,7 @@ public void GetPluginsInPATH_PATHPointsToADirectory_ContainsValidPluginFiles() // Assert Assert.Single(plugins); Assert.Equal(validPluginFile, plugins[0].Path); - Assert.True(plugins[0].IsDotnetToolsPlugin); + Assert.True(plugins[0].IsRunnablePluginFile); } [PlatformFact(Platform.Windows)] From 9bb77a9e55fb625c6d10833ef88b6a4d5826e424 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Fri, 1 Nov 2024 16:57:14 -0700 Subject: [PATCH 07/16] rename argument --- src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs index 3bcf53f171c..8f68da29bce 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs @@ -136,7 +136,7 @@ public async Task GetOrCreateAsync( var lazyTask = _plugins.GetOrAdd( filePath, (path) => new Lazy>( - () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isDotnetTools: false, sessionCancellationToken))); + () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isRunnablePluginFile: false, sessionCancellationToken))); await lazyTask.Value; @@ -149,14 +149,14 @@ private async Task CreatePluginAsync( IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, - bool isDotnetTools, + bool isRunnablePluginFile, CancellationToken sessionCancellationToken) { var args = string.Join(" ", arguments); ProcessStartInfo startInfo; - if (!isDotnetTools) + if (!isRunnablePluginFile) { #if IS_DESKTOP startInfo = new ProcessStartInfo(filePath) @@ -511,7 +511,7 @@ public async Task GetOrCreateNetToolsPluginAsync(string filePath, IEnum var lazyTask = _plugins.GetOrAdd( filePath, (path) => new Lazy>( - () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isDotnetTools: true, sessionCancellationToken))); + () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isRunnablePluginFile: true, sessionCancellationToken))); await lazyTask.Value; From 7e156cb496a4ff9efd201473f5aab69f465a4e16 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Fri, 1 Nov 2024 17:16:34 -0700 Subject: [PATCH 08/16] rename method --- .../NuGet.Protocol/Plugins/IPluginFactory.cs | 26 ++++++++++++++++++- .../NuGet.Protocol/Plugins/PluginFactory.cs | 2 +- .../NuGet.Protocol/Plugins/PluginManager.cs | 2 +- .../PublicAPI/net472/PublicAPI.Unshipped.txt | 4 +-- .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 4 +-- .../netstandard2.0/PublicAPI.Unshipped.txt | 4 +-- .../Plugins/PluginFactoryTests.cs | 2 +- 7 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs index 2053acdbe94..0f32c1cc83e 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs @@ -43,7 +43,31 @@ Task GetOrCreateAsync( ConnectionOptions options, CancellationToken sessionCancellationToken); - Task GetOrCreateNetToolsPluginAsync( + /// + /// Asynchronously retrieves an existing runnable plugin instance or creates a new instance and connects to it. + /// This method is intended for plugins that are directly executable, such as scripts or applications. + /// + /// The file path of the plugin. + /// Command-line arguments to be supplied to the plugin. + /// Request handlers. + /// Connection options. + /// A cancellation token for the plugin's lifetime. + /// A task that represents the asynchronous operation. + /// The task result () returns a + /// instance. + /// Thrown if + /// is either or empty. + /// Thrown if + /// is . + /// Thrown if + /// is . + /// Thrown if + /// is . + /// Thrown if + /// is cancelled. + /// Thrown if this object is disposed. + /// This method is primarily used for directly executable plugin files like .bat, .exe, or other runnable scripts, making it suitable for .NET tools or custom executables. + Task GetOrCreateRunnablePluginAsync( string filePath, IEnumerable arguments, IRequestHandlers requestHandlers, diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs index 8f68da29bce..b554a26ef05 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs @@ -479,7 +479,7 @@ private static void WriteCommonLogMessages(IPluginLogger logger) logger.Write(new ThreadPoolLogMessage(logger.Now)); } - public async Task GetOrCreateNetToolsPluginAsync(string filePath, IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, CancellationToken sessionCancellationToken) + public async Task GetOrCreateRunnablePluginAsync(string filePath, IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, CancellationToken sessionCancellationToken) { if (_isDisposed) { diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs index 40905b69ce0..4190b95075b 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs @@ -216,7 +216,7 @@ private async Task> TryCreatePluginAsync( if (result.PluginFile.IsRunnablePluginFile) { - plugin = await _pluginFactory.GetOrCreateNetToolsPluginAsync( + plugin = await _pluginFactory.GetOrCreateRunnablePluginAsync( filePath: result.PluginFile.Path, arguments: PluginConstants.PluginArguments, requestHandlers: new RequestHandlers(), diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt index d48329d4256..4a9670dc52f 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,4 +1,4 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt index d48329d4256..4a9670dc52f 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -1,4 +1,4 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index d48329d4256..4a9670dc52f 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,4 +1,4 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateNetToolsPluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs index 9c89bba2e52..948fe7978fa 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs @@ -158,7 +158,7 @@ echo File executed > ""{outputPath}"" var pluginFactory = new PluginFactory(Timeout.InfiniteTimeSpan); // Act - var plugin = await Assert.ThrowsAnyAsync(() => pluginFactory.GetOrCreateNetToolsPluginAsync(pluginPath, args, reqHandler, options, CancellationToken.None)); + var plugin = await Assert.ThrowsAnyAsync(() => pluginFactory.GetOrCreateRunnablePluginAsync(pluginPath, args, reqHandler, options, CancellationToken.None)); // Assert string outputContent = File.ReadAllText(outputPath); From a10f73da04c8436b9e0277cd615bc8a44ad03c15 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Mon, 4 Nov 2024 14:41:19 -0800 Subject: [PATCH 09/16] Clean up Public API --- .../NuGet.Protocol/Plugins/IPluginFactory.cs | 32 +--------- .../Plugins/PluginDiscoverer.cs | 13 ++-- .../NuGet.Protocol/Plugins/PluginFactory.cs | 60 ++----------------- .../NuGet.Protocol/Plugins/PluginFile.cs | 13 +--- .../NuGet.Protocol/Plugins/PluginManager.cs | 15 +---- .../PublicAPI/net472/PublicAPI.Shipped.txt | 3 - .../PublicAPI/net472/PublicAPI.Unshipped.txt | 5 +- .../PublicAPI/net8.0/PublicAPI.Shipped.txt | 3 - .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 5 +- .../netstandard2.0/PublicAPI.Shipped.txt | 3 - .../netstandard2.0/PublicAPI.Unshipped.txt | 5 +- .../Plugins/PluginDiscoveryResultTests.cs | 14 ++++- .../Plugins/PluginFactoryTests.cs | 20 ++++++- .../Plugins/PluginFileTests.cs | 16 ++++- .../Plugins/PluginManagerTests.cs | 36 +++++++++-- .../Plugins/PluginResourceProviderTests.cs | 27 ++++++++- 16 files changed, 128 insertions(+), 142 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs index 0f32c1cc83e..2244c4bdb82 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs @@ -41,37 +41,7 @@ Task GetOrCreateAsync( IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, + bool isRunnablePluginFile, CancellationToken sessionCancellationToken); - - /// - /// Asynchronously retrieves an existing runnable plugin instance or creates a new instance and connects to it. - /// This method is intended for plugins that are directly executable, such as scripts or applications. - /// - /// The file path of the plugin. - /// Command-line arguments to be supplied to the plugin. - /// Request handlers. - /// Connection options. - /// A cancellation token for the plugin's lifetime. - /// A task that represents the asynchronous operation. - /// The task result () returns a - /// instance. - /// Thrown if - /// is either or empty. - /// Thrown if - /// is . - /// Thrown if - /// is . - /// Thrown if - /// is . - /// Thrown if - /// is cancelled. - /// Thrown if this object is disposed. - /// This method is primarily used for directly executable plugin files like .bat, .exe, or other runnable scripts, making it suitable for .NET tools or custom executables. - Task GetOrCreateRunnablePluginAsync( - string filePath, - IEnumerable arguments, - IRequestHandlers requestHandlers, - ConnectionOptions options, - CancellationToken sessionCancellationToken); } } diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs index a91860bed47..fafa7238cfc 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs @@ -168,7 +168,7 @@ private static List GetPluginFiles(IEnumerable filePaths, Ca { return PluginFileState.InvalidFilePath; } - })); + }), isRunnablePluginFile: false); files.Add(pluginFile); } @@ -182,6 +182,11 @@ private static List GetPluginFiles(IEnumerable filePaths, Ca /// A list of valid objects representing the discovered plugins. internal List GetPluginsInNuGetPluginPaths() { + bool isDesktop = false; + +#if IS_DESKTOP + isDesktop = true; +#endif var pluginFiles = new List(); string[] paths = _nuGetPluginPaths?.Split(Path.PathSeparator) ?? Array.Empty(); @@ -205,7 +210,7 @@ internal List GetPluginsInNuGetPluginPaths() { // A non DotNet tool plugin file var state = new Lazy(() => PluginFileState.Valid); - pluginFiles.Add(new PluginFile(fileInfo.FullName, state)); + pluginFiles.Add(new PluginFile(fileInfo.FullName, state, isRunnablePluginFile: isDesktop)); } } else if (Directory.Exists(path)) @@ -215,7 +220,7 @@ internal List GetPluginsInNuGetPluginPaths() } else { - pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath))); + pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath), isRunnablePluginFile: isDesktop)); } } @@ -240,7 +245,7 @@ internal List GetPluginsInPath() } else { - pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath))); + pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath), isRunnablePluginFile: false)); } } diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs index b554a26ef05..a5354331d08 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs @@ -81,6 +81,7 @@ public void Dispose() /// Command-line arguments to be supplied to the plugin. /// Request handlers. /// Connection options. + /// Is the file a runnable file. /// A cancellation token for the plugin's lifetime. /// A task that represents the asynchronous operation. /// The task result () returns a @@ -104,6 +105,7 @@ public async Task GetOrCreateAsync( IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, + bool isRunnablePluginFile, CancellationToken sessionCancellationToken) { if (_isDisposed) @@ -136,7 +138,7 @@ public async Task GetOrCreateAsync( var lazyTask = _plugins.GetOrAdd( filePath, (path) => new Lazy>( - () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isRunnablePluginFile: false, sessionCancellationToken))); + () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isRunnablePluginFile: isRunnablePluginFile, sessionCancellationToken))); await lazyTask.Value; @@ -158,18 +160,6 @@ private async Task CreatePluginAsync( if (!isRunnablePluginFile) { -#if IS_DESKTOP - startInfo = new ProcessStartInfo(filePath) - { - Arguments = args, - UseShellExecute = false, - RedirectStandardError = false, - RedirectStandardInput = true, - RedirectStandardOutput = true, - StandardOutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), - WindowStyle = ProcessWindowStyle.Hidden, - }; -#else startInfo = new ProcessStartInfo { FileName = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? @@ -184,14 +174,12 @@ private async Task CreatePluginAsync( StandardOutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), WindowStyle = ProcessWindowStyle.Hidden, }; -#endif } else { - // A dotnet tools plugin. Execute it directly. + // Execute file directly. startInfo = new ProcessStartInfo(filePath) { - FileName = filePath, Arguments = args, UseShellExecute = false, RedirectStandardError = false, @@ -478,45 +466,5 @@ private static void WriteCommonLogMessages(IPluginLogger logger) logger.Write(new ProcessLogMessage(logger.Now)); logger.Write(new ThreadPoolLogMessage(logger.Now)); } - - public async Task GetOrCreateRunnablePluginAsync(string filePath, IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, CancellationToken sessionCancellationToken) - { - if (_isDisposed) - { - throw new ObjectDisposedException(nameof(PluginFactory)); - } - - if (string.IsNullOrEmpty(filePath)) - { - throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(filePath)); - } - - if (arguments == null) - { - throw new ArgumentNullException(nameof(arguments)); - } - - if (requestHandlers == null) - { - throw new ArgumentNullException(nameof(requestHandlers)); - } - - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - sessionCancellationToken.ThrowIfCancellationRequested(); - - var lazyTask = _plugins.GetOrAdd( - filePath, - (path) => new Lazy>( - () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isRunnablePluginFile: true, sessionCancellationToken))); - - await lazyTask.Value; - - // Manage plugin lifetime by its idleness. Thus, don't allow callers to prematurely dispose of a plugin. - return new NoOpDisposePlugin(lazyTask.Value.Result); - } } } diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs index 965f0fd1a26..7960760702b 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs @@ -31,23 +31,14 @@ public sealed class PluginFile /// The plugin's file path. /// A lazy that evaluates the plugin file state. /// Is the plugin file, a runnable plugin file? - internal PluginFile(string filePath, Lazy state, bool isRunnablePluginFile) : this(filePath, state) - { - IsRunnablePluginFile = isRunnablePluginFile; - } - - /// - /// Instantiates a new class. - /// - /// The plugin's file path. - /// A lazy that evaluates the plugin file state. - public PluginFile(string filePath, Lazy state) + public PluginFile(string filePath, Lazy state, bool isRunnablePluginFile) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(filePath)); } + IsRunnablePluginFile = isRunnablePluginFile; Path = filePath; State = state; } diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs index 4190b95075b..089e85c402b 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs @@ -214,24 +214,13 @@ private async Task> TryCreatePluginAsync( { IPlugin plugin; - if (result.PluginFile.IsRunnablePluginFile) - { - plugin = await _pluginFactory.GetOrCreateRunnablePluginAsync( + plugin = await _pluginFactory.GetOrCreateAsync( filePath: result.PluginFile.Path, arguments: PluginConstants.PluginArguments, requestHandlers: new RequestHandlers(), options: _connectionOptions, + isRunnablePluginFile: result.PluginFile.IsRunnablePluginFile, sessionCancellationToken: cancellationToken); - } - else - { - plugin = await _pluginFactory.GetOrCreateAsync( - filePath: result.PluginFile.Path, - arguments: PluginConstants.PluginArguments, - requestHandlers: new RequestHandlers(), - options: _connectionOptions, - sessionCancellationToken: cancellationToken); - } var utilities = await PerformOneTimePluginInitializationAsync(plugin, cancellationToken); diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt index def020375d4..4043f67eccf 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt @@ -1016,7 +1016,6 @@ NuGet.Protocol.Plugins.IPlugin.Closed -> System.EventHandler NuGet.Protocol.Plugins.IPluginDiscoverer ~NuGet.Protocol.Plugins.IPluginDiscoverer.DiscoverAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> NuGet.Protocol.Plugins.IPluginFactory -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task NuGet.Protocol.Plugins.IPluginManager ~NuGet.Protocol.Plugins.IPluginManager.CreatePluginsAsync(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> ~NuGet.Protocol.Plugins.IPluginManager.FindAvailablePluginsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> @@ -1212,11 +1211,9 @@ NuGet.Protocol.Plugins.PluginException ~NuGet.Protocol.Plugins.PluginException.PluginException(string message, System.Exception innerException) -> void NuGet.Protocol.Plugins.PluginFactory NuGet.Protocol.Plugins.PluginFactory.Dispose() -> void -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task NuGet.Protocol.Plugins.PluginFactory.PluginFactory(System.TimeSpan pluginIdleTimeout) -> void NuGet.Protocol.Plugins.PluginFile ~NuGet.Protocol.Plugins.PluginFile.Path.get -> string -~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state) -> void ~NuGet.Protocol.Plugins.PluginFile.State.get -> System.Lazy NuGet.Protocol.Plugins.PluginFileState NuGet.Protocol.Plugins.PluginFileState.InvalidEmbeddedSignature = 3 -> NuGet.Protocol.Plugins.PluginFileState diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt index 4a9670dc52f..d465a4e755a 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,4 +1,5 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool isRunnablePluginFile) -> void diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt index 86a9ec539e4..fbc3dca5680 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt @@ -1016,7 +1016,6 @@ NuGet.Protocol.Plugins.IPlugin.Closed -> System.EventHandler NuGet.Protocol.Plugins.IPluginDiscoverer ~NuGet.Protocol.Plugins.IPluginDiscoverer.DiscoverAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> NuGet.Protocol.Plugins.IPluginFactory -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task NuGet.Protocol.Plugins.IPluginManager ~NuGet.Protocol.Plugins.IPluginManager.CreatePluginsAsync(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> ~NuGet.Protocol.Plugins.IPluginManager.FindAvailablePluginsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> @@ -1212,11 +1211,9 @@ NuGet.Protocol.Plugins.PluginException ~NuGet.Protocol.Plugins.PluginException.PluginException(string message, System.Exception innerException) -> void NuGet.Protocol.Plugins.PluginFactory NuGet.Protocol.Plugins.PluginFactory.Dispose() -> void -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task NuGet.Protocol.Plugins.PluginFactory.PluginFactory(System.TimeSpan pluginIdleTimeout) -> void NuGet.Protocol.Plugins.PluginFile ~NuGet.Protocol.Plugins.PluginFile.Path.get -> string -~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state) -> void ~NuGet.Protocol.Plugins.PluginFile.State.get -> System.Lazy NuGet.Protocol.Plugins.PluginFileState NuGet.Protocol.Plugins.PluginFileState.InvalidEmbeddedSignature = 3 -> NuGet.Protocol.Plugins.PluginFileState diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt index 4a9670dc52f..d465a4e755a 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -1,4 +1,5 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool isRunnablePluginFile) -> void diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt index 86a9ec539e4..fbc3dca5680 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt @@ -1016,7 +1016,6 @@ NuGet.Protocol.Plugins.IPlugin.Closed -> System.EventHandler NuGet.Protocol.Plugins.IPluginDiscoverer ~NuGet.Protocol.Plugins.IPluginDiscoverer.DiscoverAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> NuGet.Protocol.Plugins.IPluginFactory -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task NuGet.Protocol.Plugins.IPluginManager ~NuGet.Protocol.Plugins.IPluginManager.CreatePluginsAsync(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> ~NuGet.Protocol.Plugins.IPluginManager.FindAvailablePluginsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> @@ -1212,11 +1211,9 @@ NuGet.Protocol.Plugins.PluginException ~NuGet.Protocol.Plugins.PluginException.PluginException(string message, System.Exception innerException) -> void NuGet.Protocol.Plugins.PluginFactory NuGet.Protocol.Plugins.PluginFactory.Dispose() -> void -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task NuGet.Protocol.Plugins.PluginFactory.PluginFactory(System.TimeSpan pluginIdleTimeout) -> void NuGet.Protocol.Plugins.PluginFile ~NuGet.Protocol.Plugins.PluginFile.Path.get -> string -~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state) -> void ~NuGet.Protocol.Plugins.PluginFile.State.get -> System.Lazy NuGet.Protocol.Plugins.PluginFileState NuGet.Protocol.Plugins.PluginFileState.InvalidEmbeddedSignature = 3 -> NuGet.Protocol.Plugins.PluginFileState diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 4a9670dc52f..d465a4e755a 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,4 +1,5 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateRunnablePluginAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool isRunnablePluginFile) -> void diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscoveryResultTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscoveryResultTests.cs index 17493c4913b..771054b90dd 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscoveryResultTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscoveryResultTests.cs @@ -8,6 +8,18 @@ namespace NuGet.Protocol.Plugins.Tests { public class PluginDiscoveryResultTests { + public bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } + [Fact] public void Constructor_ThrowsForNullPluginFile() { @@ -20,7 +32,7 @@ public void Constructor_ThrowsForNullPluginFile() [Fact] public void Constructor_InitializesProperties() { - var pluginFile = new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.InvalidEmbeddedSignature)); + var pluginFile = new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.InvalidEmbeddedSignature), isRunnablePluginFile: IsDesktop); var result = new PluginDiscoveryResult(pluginFile); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs index 948fe7978fa..3c00ba8b5c9 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs @@ -12,6 +12,18 @@ namespace NuGet.Protocol.Plugins.Tests { public class PluginFactoryTests { + public bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } + [Fact] public void Constructor_ThrowsForTimeSpanBelowMinimum() { @@ -52,6 +64,7 @@ public async Task GetOrCreateAsync_ThrowsForNullOrEmptyFilePath(string filePath) PluginConstants.PluginArguments, new RequestHandlers(), ConnectionOptions.CreateDefault(), + isRunnablePluginFile: IsDesktop, CancellationToken.None)); Assert.Equal("filePath", exception.ParamName); @@ -68,6 +81,7 @@ public async Task GetOrCreateAsync_ThrowsForNullArguments() arguments: null, requestHandlers: new RequestHandlers(), options: ConnectionOptions.CreateDefault(), + isRunnablePluginFile: IsDesktop, sessionCancellationToken: CancellationToken.None)); Assert.Equal("arguments", exception.ParamName); @@ -84,6 +98,7 @@ public async Task GetOrCreateAsync_ThrowsForNullRequestHandlers() arguments: PluginConstants.PluginArguments, requestHandlers: null, options: ConnectionOptions.CreateDefault(), + isRunnablePluginFile: IsDesktop, sessionCancellationToken: CancellationToken.None)); Assert.Equal("requestHandlers", exception.ParamName); @@ -100,6 +115,7 @@ public async Task GetOrCreateAsync_ThrowsForNullConnectionOptions() arguments: PluginConstants.PluginArguments, requestHandlers: new RequestHandlers(), options: null, + isRunnablePluginFile: IsDesktop, sessionCancellationToken: CancellationToken.None)); Assert.Equal("options", exception.ParamName); @@ -116,6 +132,7 @@ await Assert.ThrowsAsync( arguments: PluginConstants.PluginArguments, requestHandlers: new RequestHandlers(), options: ConnectionOptions.CreateDefault(), + isRunnablePluginFile: IsDesktop, sessionCancellationToken: new CancellationToken(canceled: true))); } @@ -132,6 +149,7 @@ public async Task GetOrCreateAsync_ThrowsIfDisposed() arguments: PluginConstants.PluginArguments, requestHandlers: new RequestHandlers(), options: ConnectionOptions.CreateDefault(), + isRunnablePluginFile: IsDesktop, sessionCancellationToken: CancellationToken.None)); Assert.Equal(nameof(PluginFactory), exception.ObjectName); @@ -158,7 +176,7 @@ echo File executed > ""{outputPath}"" var pluginFactory = new PluginFactory(Timeout.InfiniteTimeSpan); // Act - var plugin = await Assert.ThrowsAnyAsync(() => pluginFactory.GetOrCreateRunnablePluginAsync(pluginPath, args, reqHandler, options, CancellationToken.None)); + var plugin = await Assert.ThrowsAnyAsync(() => pluginFactory.GetOrCreateAsync(pluginPath, args, reqHandler, options, isRunnablePluginFile: true, CancellationToken.None)); // Assert string outputContent = File.ReadAllText(outputPath); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFileTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFileTests.cs index 660f690216f..40cf68cd0a0 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFileTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFileTests.cs @@ -8,12 +8,24 @@ namespace NuGet.Protocol.Plugins.Tests { public class PluginFileTests { + public bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } + [Theory] [InlineData(null)] [InlineData("")] public void Constructor_ThrowsForNullOrEmptyFilePath(string filePath) { - var exception = Assert.Throws(() => new PluginFile(filePath, state: new Lazy(() => PluginFileState.NotFound))); + var exception = Assert.Throws(() => new PluginFile(filePath, state: new Lazy(() => PluginFileState.NotFound), isRunnablePluginFile: IsDesktop)); Assert.Equal("filePath", exception.ParamName); } @@ -21,7 +33,7 @@ public void Constructor_ThrowsForNullOrEmptyFilePath(string filePath) [Fact] public void Constructor_InitializesProperties() { - var pluginFile = new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.Valid)); + var pluginFile = new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop); Assert.Equal("a", pluginFile.Path); Assert.Equal(PluginFileState.Valid, pluginFile.State.Value); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs index 07e965955e3..628b8aca43c 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs @@ -17,6 +17,17 @@ namespace NuGet.Protocol.Plugins.Tests public class PluginManagerTests { private const string PluginFilePath = "a"; + public bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } [Fact] public async Task TryGetSourceAgnosticPluginAsync_WhenExceptionIsThrownDuringPluginCreation_PropagatesException() @@ -32,6 +43,7 @@ public async Task TryGetSourceAgnosticPluginAsync_WhenExceptionIsThrownDuringPlu It.Is>(arguments => arguments != null && arguments.Any()), It.IsNotNull(), It.IsNotNull(), + It.IsAny(), It.IsAny())) .ThrowsAsync(exception); pluginFactory.Setup(x => x.Dispose()); @@ -46,7 +58,7 @@ public async Task TryGetSourceAgnosticPluginAsync_WhenExceptionIsThrownDuringPlu var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid))); + new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); Tuple result = await pluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -77,7 +89,7 @@ public async Task TryGetSourceAgnosticPluginAsync_WhenSuccessfullyCreated_Operat var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid))); + new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); Tuple result = await test.PluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -115,7 +127,7 @@ public async Task TryGetSourceAgnosticPluginAsync_WhenCacheFileIndicatesIndicate var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid))); + new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); Tuple result = await test.PluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -164,7 +176,7 @@ public async Task PluginManager_CreatePlugin_PrefersFrameworkSpecificEnvironment var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid))); + new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); Tuple result = await test.PluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -214,7 +226,7 @@ public async Task PluginManager_CreatePlugin_EmptyFrameworkSpecificEnvironmentVa var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid))); + new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); Tuple result = await test.PluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -236,6 +248,17 @@ public async Task PluginManager_CreatePlugin_EmptyFrameworkSpecificEnvironmentVa private sealed class PluginManagerTest : IDisposable { + public bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } private readonly Mock _connection; private readonly Mock _factory; private readonly Mock _plugin; @@ -289,7 +312,7 @@ internal PluginManagerTest( _pluginDiscoverer.Setup(x => x.DiscoverAsync(It.IsAny())) .ReturnsAsync(new[] { - new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState))) + new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState), isRunnablePluginFile: IsDesktop)) }); _connection = new Mock(MockBehavior.Strict); @@ -335,6 +358,7 @@ internal PluginManagerTest( It.IsNotNull>(), It.IsNotNull(), It.IsNotNull(), + It.IsAny(), It.IsAny())) .ReturnsAsync(_plugin.Object); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs index 787f6b6db73..bac8116dfc0 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs @@ -226,6 +226,17 @@ private static SourceRepository CreateSourceRepository( private sealed class PluginResourceProviderNegativeTest : IDisposable { + public static bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } private readonly Mock _pluginDiscoverer; private readonly PluginManager _pluginManager; private readonly Mock _environmentVariableReader; @@ -299,7 +310,7 @@ private static IEnumerable GetPluginDiscoveryResults(stri foreach (var path in pluginPaths.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { var state = path == "a" ? PluginFileState.Valid : PluginFileState.InvalidEmbeddedSignature; - var file = new PluginFile(path, new Lazy(() => state)); + var file = new PluginFile(path, new Lazy(() => state), isRunnablePluginFile: IsDesktop); results.Add(new PluginDiscoveryResult(file)); } @@ -309,6 +320,17 @@ private static IEnumerable GetPluginDiscoveryResults(stri private sealed class PluginResourceProviderPositiveTest : IDisposable { + public static bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } private readonly Mock _connection; private readonly IEnumerable _expectations; private readonly Mock _factory; @@ -355,7 +377,7 @@ internal PluginResourceProviderPositiveTest( _pluginDiscoverer.Setup(x => x.DiscoverAsync(It.IsAny())) .ReturnsAsync(new[] { - new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState))) + new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState), isRunnablePluginFile: IsDesktop)) }); _connection = new Mock(MockBehavior.Strict); @@ -415,6 +437,7 @@ internal PluginResourceProviderPositiveTest( It.IsNotNull>(), It.IsNotNull(), It.IsNotNull(), + It.IsAny(), It.IsAny())) .ReturnsAsync(_plugin.Object); From 216f37f6f9dd66fc4b34c11c1e5288d65c488d5f Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Mon, 4 Nov 2024 15:07:08 -0800 Subject: [PATCH 10/16] fix --- .../NuGet.Protocol.FuncTest/PluginTests.cs | 17 ++++++++++ .../PluginManagerMock.cs | 15 ++++++++- ...urePluginCredentialProviderBuilderTests.cs | 13 +++++++- .../SecurePluginCredentialProviderTests.cs | 32 +++++++++++++------ 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/PluginTests.cs b/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/PluginTests.cs index 157f638d25e..bd41b04e31b 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/PluginTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/PluginTests.cs @@ -26,6 +26,18 @@ namespace NuGet.Protocol.FuncTest { public class PluginTests { + public static bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } + private static readonly FileInfo PluginFile; private static readonly ushort PortNumber = 11000; private static readonly IEnumerable PluginArguments = PluginConstants.PluginArguments @@ -64,6 +76,7 @@ public async Task GetOrCreateAsync_WithUnhandledExceptionInPlugin_Throws() PluginConstants.PluginArguments.Concat(new[] { "-ThrowException Unhandled" }), new RequestHandlers(), ConnectionOptions.CreateDefault(), + isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token)); Assert.True( @@ -85,6 +98,7 @@ public async Task GetOrCreateAsync_WithHandledExceptionAndExitInPlugin_Throws() PluginConstants.PluginArguments.Concat(new[] { "-ThrowException Handled" }), new RequestHandlers(), ConnectionOptions.CreateDefault(), + isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token)); Assert.True( @@ -106,6 +120,7 @@ public async Task GetOrCreateAsync_WhenPluginFreezes_Throws() PluginConstants.PluginArguments.Concat(new[] { "-Freeze" }), new RequestHandlers(), ConnectionOptions.CreateDefault(), + isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token)); Assert.True( @@ -127,6 +142,7 @@ public async Task GetOrCreateAsync_WhenPluginCausesProtocolException_Throws() PluginConstants.PluginArguments.Concat(new[] { "-CauseProtocolException" }), new RequestHandlers(), ConnectionOptions.CreateDefault(), + isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token)); Assert.Equal("Plugin 'Plugin.Testable' failed with the exception: The plugin handshake failed.", exception.Message); @@ -322,6 +338,7 @@ internal static async Task CreateAsync() PluginArguments, new RequestHandlers(), options, + isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token); var responseSender = new ResponseSender(PortNumber); diff --git a/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs b/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs index 7273edc056e..90f50603331 100644 --- a/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs +++ b/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs @@ -66,6 +66,18 @@ internal TestExpectation( internal sealed class PluginManagerMock : IDisposable { + public static bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } + private readonly Mock _connection; private readonly TestExpectation _expectations; private readonly Mock _factory; @@ -238,7 +250,7 @@ private void EnsureDiscovererIsCalled(string pluginFilePath, PluginFileState plu _pluginDiscoverer.Setup(x => x.DiscoverAsync(It.IsAny())) .ReturnsAsync(new[] { - new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState))) + new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState), isRunnablePluginFile: IsDesktop)) }); } @@ -285,6 +297,7 @@ private void EnsureFactorySetupCalls(string pluginFilePath) It.IsNotNull>(), It.IsNotNull(), It.IsNotNull(), + It.IsAny(), It.IsAny())) .ReturnsAsync(_plugin.Object); } diff --git a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs index 9acf4a02f70..88970d78a1a 100644 --- a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs @@ -17,6 +17,17 @@ namespace NuGet.Credentials.Test { public class SecurePluginCredentialProviderBuilderTests : IDisposable { + public static bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } private readonly TestDirectory _testDirectory; public SecurePluginCredentialProviderBuilderTests() @@ -170,7 +181,7 @@ private static IEnumerable GetPluginDiscoveryResults(List var results = new List(); foreach (var plugin in plugins) { - var file = new PluginFile(plugin.Key, new Lazy(() => plugin.Value)); + var file = new PluginFile(plugin.Key, new Lazy(() => plugin.Value), isRunnablePluginFile: IsDesktop); results.Add(new PluginDiscoveryResult(file)); } diff --git a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs index bbf4d232df5..aa003ceff16 100644 --- a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs @@ -17,6 +17,18 @@ namespace NuGet.Credentials.Test { public sealed class SecurePluginCredentialProviderTests : IDisposable { + public bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } + private static readonly Uri _uri = new Uri("https://unit.test"); private const string _username = "username"; private const string _password = "password"; @@ -94,7 +106,7 @@ public async Task GetAsync_WithValidArguments_ReturnsValidCredentials() pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid))); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -129,7 +141,7 @@ public async Task GetAsync_WhenCalledMultipleTimes_DoesNotCreateMultipleInstance pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid))); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -166,7 +178,7 @@ public async Task GetAsync_WhenPluginClaimsMultipleOperations_ReturnsValidCreden pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid))); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -206,7 +218,7 @@ public async Task GetAsync_WhenProxyIsUsed_SetsProxyCredentials() pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid))); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); var proxy = new System.Net.WebProxy() { @@ -243,7 +255,7 @@ public async Task GetAsync_WhenCalledMultipleTimes_CachesCapabilities() pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid))); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -273,7 +285,7 @@ public async Task GetAsync_WhenCalledMultipleTimes_CachesCapabilities() pluginFileState: PluginFileState.Valid, expectations: expectations2)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid))); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -311,7 +323,7 @@ public async Task GetAsync_SendsCorrectCanShowDialogValue() pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid))); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -344,7 +356,7 @@ public async Task GetAsync_WhenPluginManagerReturnsException_ExceptionIsPropagat It.IsAny())) .ReturnsAsync(result); - var pluginDiscoveryResult = new PluginDiscoveryResult(new PluginFile("c", new Lazy(() => PluginFileState.Valid))); + var pluginDiscoveryResult = new PluginDiscoveryResult(new PluginFile("c", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); var logger = new Mock(MockBehavior.Strict); logger.Setup(x => x.LogError(It.Is(data => data == expectedMessage))); @@ -379,7 +391,7 @@ public async Task GetAsync_WhenCredentialPluginIsUnableToAcquireCredentials_Retu pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid))); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -397,7 +409,7 @@ public async Task GetAsync_WhenCredentialPluginIsUnableToAcquireCredentials_Retu private PluginDiscoveryResult CreatePluginDiscoveryResult(PluginFileState pluginState = PluginFileState.Valid) { - return new PluginDiscoveryResult(new PluginFile(Path.Combine(_testDirectory.Path, "plugin.exe"), new Lazy(() => pluginState))); + return new PluginDiscoveryResult(new PluginFile(Path.Combine(_testDirectory.Path, "plugin.exe"), new Lazy(() => pluginState), isRunnablePluginFile: IsDesktop)); } private PluginManager CreateDefaultPluginManager() From 9aadd888ccf3832a21f4b7f0f77109ac721dde5b Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Mon, 4 Nov 2024 15:30:43 -0800 Subject: [PATCH 11/16] Fix --- .../NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs index 4210cbc1b57..098a72bc3a6 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs @@ -525,7 +525,6 @@ public void GetPluginsInNuGetPluginPaths_NuGetPluginPathsPointsToAFileThatDoesNo // Assert Assert.Single(plugins); - Assert.False(plugins[0].IsRunnablePluginFile); } [PlatformFact(Platform.Windows)] From 0c38f346e515f7b75b2fcf5df2edefd679689907 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Tue, 5 Nov 2024 16:10:20 -0800 Subject: [PATCH 12/16] Update GetOrCreateAsync Api to use PluginFile --- .../NuGet.Protocol/Plugins/IPluginFactory.cs | 7 +++-- .../Plugins/PluginDiscoverer.cs | 12 ++++----- .../NuGet.Protocol/Plugins/PluginFactory.cs | 27 +++++++++---------- .../NuGet.Protocol/Plugins/PluginFile.cs | 10 +++---- .../NuGet.Protocol/Plugins/PluginManager.cs | 3 +-- .../PublicAPI/net472/PublicAPI.Unshipped.txt | 6 ++--- .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 6 ++--- .../netstandard2.0/PublicAPI.Unshipped.txt | 6 ++--- .../NuGet.Protocol.FuncTest/PluginTests.cs | 15 ++++------- .../Plugins/PluginDiscovererTests.cs | 8 +++--- .../Plugins/PluginDiscoveryResultTests.cs | 2 +- .../Plugins/PluginFactoryTests.cs | 20 +++++--------- .../Plugins/PluginFileTests.cs | 4 +-- .../Plugins/PluginManagerTests.cs | 18 ++++++------- .../Plugins/PluginResourceProviderTests.cs | 7 +++-- 15 files changed, 66 insertions(+), 85 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs index 2244c4bdb82..4509749111d 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs @@ -16,7 +16,7 @@ public interface IPluginFactory : IDisposable /// /// Asynchronously gets an existing plugin instance or creates a new instance and connects to it. /// - /// The file path of the plugin. + /// A plugin file. /// Command-line arguments to be supplied to the plugin. /// Request handlers. /// Connection options. @@ -24,7 +24,7 @@ public interface IPluginFactory : IDisposable /// A task that represents the asynchronous operation. /// The task result () returns a /// instance. - /// Thrown if + /// Thrown if /// is either or empty. /// Thrown if /// is . @@ -37,11 +37,10 @@ public interface IPluginFactory : IDisposable /// Thrown if this object is disposed. /// This is intended to be called by NuGet client tools. Task GetOrCreateAsync( - string filePath, + PluginFile pluginFile, IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, - bool isRunnablePluginFile, CancellationToken sessionCancellationToken); } } diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs index fafa7238cfc..5ffe1d3c97d 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs @@ -168,7 +168,7 @@ private static List GetPluginFiles(IEnumerable filePaths, Ca { return PluginFileState.InvalidFilePath; } - }), isRunnablePluginFile: false); + }), requiresDotnetHost: true); files.Add(pluginFile); } @@ -202,7 +202,7 @@ internal List GetPluginsInNuGetPluginPaths() // A DotNet tool plugin if (IsValidPluginFile(fileInfo)) { - PluginFile pluginFile = new PluginFile(fileInfo.FullName, new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: true); + PluginFile pluginFile = new PluginFile(fileInfo.FullName, new Lazy(() => PluginFileState.Valid), requiresDotnetHost: false); pluginFiles.Add(pluginFile); } } @@ -210,7 +210,7 @@ internal List GetPluginsInNuGetPluginPaths() { // A non DotNet tool plugin file var state = new Lazy(() => PluginFileState.Valid); - pluginFiles.Add(new PluginFile(fileInfo.FullName, state, isRunnablePluginFile: isDesktop)); + pluginFiles.Add(new PluginFile(fileInfo.FullName, state, requiresDotnetHost: !isDesktop)); } } else if (Directory.Exists(path)) @@ -220,7 +220,7 @@ internal List GetPluginsInNuGetPluginPaths() } else { - pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath), isRunnablePluginFile: isDesktop)); + pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath), requiresDotnetHost: !isDesktop)); } } @@ -245,7 +245,7 @@ internal List GetPluginsInPath() } else { - pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath), isRunnablePluginFile: false)); + pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath), requiresDotnetHost: false)); } } @@ -265,7 +265,7 @@ private static List GetNetToolsPluginsInDirectory(string directoryPa { if (IsValidPluginFile(file)) { - PluginFile pluginFile = new PluginFile(file.FullName, new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: true); + PluginFile pluginFile = new PluginFile(file.FullName, new Lazy(() => PluginFileState.Valid), requiresDotnetHost: false); pluginFiles.Add(pluginFile); } } diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs index a5354331d08..1915bc8714d 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs @@ -77,16 +77,15 @@ public void Dispose() /// /// Asynchronously gets an existing plugin instance or creates a new instance and connects to it. /// - /// The file path of the plugin. + /// A plugin file. /// Command-line arguments to be supplied to the plugin. /// Request handlers. /// Connection options. - /// Is the file a runnable file. /// A cancellation token for the plugin's lifetime. /// A task that represents the asynchronous operation. /// The task result () returns a /// instance. - /// Thrown if + /// Thrown if /// is either or empty. /// Thrown if /// is . @@ -101,11 +100,10 @@ public void Dispose() /// Thrown for a plugin failure during creation. /// This is intended to be called by NuGet client tools. public async Task GetOrCreateAsync( - string filePath, + PluginFile pluginFile, IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, - bool isRunnablePluginFile, CancellationToken sessionCancellationToken) { if (_isDisposed) @@ -113,9 +111,9 @@ public async Task GetOrCreateAsync( throw new ObjectDisposedException(nameof(PluginFactory)); } - if (string.IsNullOrEmpty(filePath)) + if (string.IsNullOrEmpty(pluginFile.Path)) { - throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(filePath)); + throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(pluginFile.Path)); } if (arguments == null) @@ -136,9 +134,9 @@ public async Task GetOrCreateAsync( sessionCancellationToken.ThrowIfCancellationRequested(); var lazyTask = _plugins.GetOrAdd( - filePath, + pluginFile.Path, (path) => new Lazy>( - () => CreatePluginAsync(filePath, arguments, requestHandlers, options, isRunnablePluginFile: isRunnablePluginFile, sessionCancellationToken))); + () => CreatePluginAsync(pluginFile, arguments, requestHandlers, options, sessionCancellationToken))); await lazyTask.Value; @@ -147,18 +145,17 @@ public async Task GetOrCreateAsync( } private async Task CreatePluginAsync( - string filePath, + PluginFile pluginFile, IEnumerable arguments, IRequestHandlers requestHandlers, ConnectionOptions options, - bool isRunnablePluginFile, CancellationToken sessionCancellationToken) { var args = string.Join(" ", arguments); ProcessStartInfo startInfo; - if (!isRunnablePluginFile) + if (pluginFile.RequiresDotnetHost) { startInfo = new ProcessStartInfo { @@ -166,7 +163,7 @@ private async Task CreatePluginAsync( (NuGet.Common.RuntimeEnvironmentHelper.IsWindows ? "dotnet.exe" : "dotnet"), - Arguments = $"\"{filePath}\" " + args, + Arguments = $"\"{pluginFile.Path}\" " + args, UseShellExecute = false, RedirectStandardError = false, RedirectStandardInput = true, @@ -178,7 +175,7 @@ private async Task CreatePluginAsync( else { // Execute file directly. - startInfo = new ProcessStartInfo(filePath) + startInfo = new ProcessStartInfo(pluginFile.Path) { Arguments = args, UseShellExecute = false, @@ -230,7 +227,7 @@ private async Task CreatePluginAsync( connection = new Connection(messageDispatcher, sender, receiver, options, _logger); var plugin = new Plugin( - filePath, + pluginFile.Path, connection, pluginProcess, isOwnProcess: false, diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs index 7960760702b..0d4f799d0e0 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFile.cs @@ -21,24 +21,24 @@ public sealed class PluginFile public Lazy State { get; } /// - /// Indicates if the plugin file is runnable, such as an executable or a script. + /// Indicates if the plugin file requires a dotnet host. /// - internal bool IsRunnablePluginFile { get; } + internal bool RequiresDotnetHost { get; } /// /// Instantiates a new class. /// /// The plugin's file path. /// A lazy that evaluates the plugin file state. - /// Is the plugin file, a runnable plugin file? - public PluginFile(string filePath, Lazy state, bool isRunnablePluginFile) + /// Indicates if the plugin file requires a dotnet host. + public PluginFile(string filePath, Lazy state, bool requiresDotnetHost) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(filePath)); } - IsRunnablePluginFile = isRunnablePluginFile; + RequiresDotnetHost = requiresDotnetHost; Path = filePath; State = state; } diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs index 089e85c402b..c3a9a34a818 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs @@ -215,11 +215,10 @@ private async Task> TryCreatePluginAsync( IPlugin plugin; plugin = await _pluginFactory.GetOrCreateAsync( - filePath: result.PluginFile.Path, + pluginFile: result.PluginFile, arguments: PluginConstants.PluginArguments, requestHandlers: new RequestHandlers(), options: _connectionOptions, - isRunnablePluginFile: result.PluginFile.IsRunnablePluginFile, sessionCancellationToken: cancellationToken); var utilities = await PerformOneTimePluginInitializationAsync(plugin, cancellationToken); diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt index d465a4e755a..1507646b1ff 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool isRunnablePluginFile) -> void +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool requiresDotnetHost) -> void diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt index d465a4e755a..1507646b1ff 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool isRunnablePluginFile) -> void +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool requiresDotnetHost) -> void diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index d465a4e755a..1507646b1ff 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(string filePath, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, bool isRunnablePluginFile, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task -~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool isRunnablePluginFile) -> void +~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool requiresDotnetHost) -> void diff --git a/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/PluginTests.cs b/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/PluginTests.cs index bd41b04e31b..4fc22ae9e0d 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/PluginTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/PluginTests.cs @@ -72,11 +72,10 @@ public async Task GetOrCreateAsync_WithUnhandledExceptionInPlugin_Throws() using (var pluginFactory = new PluginFactory(PluginConstants.IdleTimeout)) { var exception = await Assert.ThrowsAsync(() => pluginFactory.GetOrCreateAsync( - PluginFile.FullName, + new PluginFile(filePath: PluginFile.FullName, state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), PluginConstants.PluginArguments.Concat(new[] { "-ThrowException Unhandled" }), new RequestHandlers(), ConnectionOptions.CreateDefault(), - isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token)); Assert.True( @@ -94,11 +93,10 @@ public async Task GetOrCreateAsync_WithHandledExceptionAndExitInPlugin_Throws() using (var pluginFactory = new PluginFactory(PluginConstants.IdleTimeout)) { var exception = await Assert.ThrowsAsync(() => pluginFactory.GetOrCreateAsync( - PluginFile.FullName, + new PluginFile(filePath: PluginFile.FullName, state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), PluginConstants.PluginArguments.Concat(new[] { "-ThrowException Handled" }), new RequestHandlers(), ConnectionOptions.CreateDefault(), - isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token)); Assert.True( @@ -116,11 +114,10 @@ public async Task GetOrCreateAsync_WhenPluginFreezes_Throws() using (var pluginFactory = new PluginFactory(PluginConstants.IdleTimeout)) { var exception = await Assert.ThrowsAsync(() => pluginFactory.GetOrCreateAsync( - PluginFile.FullName, + new PluginFile(filePath: PluginFile.FullName, state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), PluginConstants.PluginArguments.Concat(new[] { "-Freeze" }), new RequestHandlers(), ConnectionOptions.CreateDefault(), - isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token)); Assert.True( @@ -138,11 +135,10 @@ public async Task GetOrCreateAsync_WhenPluginCausesProtocolException_Throws() using (var pluginFactory = new PluginFactory(PluginConstants.IdleTimeout)) { var exception = await Assert.ThrowsAsync(() => pluginFactory.GetOrCreateAsync( - PluginFile.FullName, + new PluginFile(filePath: PluginFile.FullName, state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), PluginConstants.PluginArguments.Concat(new[] { "-CauseProtocolException" }), new RequestHandlers(), ConnectionOptions.CreateDefault(), - isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token)); Assert.Equal("Plugin 'Plugin.Testable' failed with the exception: The plugin handshake failed.", exception.Message); @@ -334,11 +330,10 @@ internal static async Task CreateAsync() var pluginFactory = new PluginFactory(PluginConstants.IdleTimeout); var options = ConnectionOptions.CreateDefault(); var plugin = await pluginFactory.GetOrCreateAsync( - PluginFile.FullName, + new PluginFile(filePath: PluginFile.FullName, state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), PluginArguments, new RequestHandlers(), options, - isRunnablePluginFile: IsDesktop, cancellationTokenSource.Token); var responseSender = new ResponseSender(PortNumber); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs index 098a72bc3a6..317dc08d39c 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscovererTests.cs @@ -436,7 +436,7 @@ public void GetPluginsInNuGetPluginPaths_WithNuGetPluginPathsSet_ReturnsPluginsI // Assert Assert.Single(plugins); Assert.Equal(pluginInNuGetPluginPathDirectoryFilePath, plugins[0].Path); - Assert.True(plugins[0].IsRunnablePluginFile); + Assert.False(plugins[0].RequiresDotnetHost); } [PlatformFact(Platform.Windows)] @@ -480,7 +480,7 @@ public void GetPluginsInPATH_WithPATHSet_ReturnsPlugin() // Assert Assert.Single(plugins); Assert.Equal(pluginInPathDirectoryFilePath, plugins[0].Path); - Assert.True(plugins[0].IsRunnablePluginFile); + Assert.False(plugins[0].RequiresDotnetHost); } [PlatformFact(Platform.Windows)] @@ -503,7 +503,7 @@ public void GetPluginsInNuGetPluginPaths_NuGetPluginPathsPointsToAFile_TreatsAsP // Assert Assert.Single(plugins); Assert.Equal(pluginFilePath, plugins[0].Path); - Assert.True(plugins[0].IsRunnablePluginFile); + Assert.False(plugins[0].RequiresDotnetHost); } [PlatformFact(Platform.Windows)] @@ -548,7 +548,7 @@ public void GetPluginsInPATH_PATHPointsToADirectory_ContainsValidPluginFiles() // Assert Assert.Single(plugins); Assert.Equal(validPluginFile, plugins[0].Path); - Assert.True(plugins[0].IsRunnablePluginFile); + Assert.False(plugins[0].RequiresDotnetHost); } [PlatformFact(Platform.Windows)] diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscoveryResultTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscoveryResultTests.cs index 771054b90dd..2c5b57521e6 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscoveryResultTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginDiscoveryResultTests.cs @@ -32,7 +32,7 @@ public void Constructor_ThrowsForNullPluginFile() [Fact] public void Constructor_InitializesProperties() { - var pluginFile = new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.InvalidEmbeddedSignature), isRunnablePluginFile: IsDesktop); + var pluginFile = new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.InvalidEmbeddedSignature), requiresDotnetHost: !IsDesktop); var result = new PluginDiscoveryResult(pluginFile); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs index 3c00ba8b5c9..bffb021f6f6 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFactoryTests.cs @@ -60,11 +60,10 @@ public async Task GetOrCreateAsync_ThrowsForNullOrEmptyFilePath(string filePath) var exception = await Assert.ThrowsAsync( () => factory.GetOrCreateAsync( - filePath, + new PluginFile(filePath: filePath, state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), PluginConstants.PluginArguments, new RequestHandlers(), ConnectionOptions.CreateDefault(), - isRunnablePluginFile: IsDesktop, CancellationToken.None)); Assert.Equal("filePath", exception.ParamName); @@ -77,11 +76,10 @@ public async Task GetOrCreateAsync_ThrowsForNullArguments() var exception = await Assert.ThrowsAsync( () => factory.GetOrCreateAsync( - filePath: "a", + new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), arguments: null, requestHandlers: new RequestHandlers(), options: ConnectionOptions.CreateDefault(), - isRunnablePluginFile: IsDesktop, sessionCancellationToken: CancellationToken.None)); Assert.Equal("arguments", exception.ParamName); @@ -94,11 +92,10 @@ public async Task GetOrCreateAsync_ThrowsForNullRequestHandlers() var exception = await Assert.ThrowsAsync( () => factory.GetOrCreateAsync( - filePath: "a", + new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), arguments: PluginConstants.PluginArguments, requestHandlers: null, options: ConnectionOptions.CreateDefault(), - isRunnablePluginFile: IsDesktop, sessionCancellationToken: CancellationToken.None)); Assert.Equal("requestHandlers", exception.ParamName); @@ -111,11 +108,10 @@ public async Task GetOrCreateAsync_ThrowsForNullConnectionOptions() var exception = await Assert.ThrowsAsync( () => factory.GetOrCreateAsync( - filePath: "a", + new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), arguments: PluginConstants.PluginArguments, requestHandlers: new RequestHandlers(), options: null, - isRunnablePluginFile: IsDesktop, sessionCancellationToken: CancellationToken.None)); Assert.Equal("options", exception.ParamName); @@ -128,11 +124,10 @@ public async Task GetOrCreateAsync_ThrowsIfCancelled() await Assert.ThrowsAsync( () => factory.GetOrCreateAsync( - filePath: "a", + new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), arguments: PluginConstants.PluginArguments, requestHandlers: new RequestHandlers(), options: ConnectionOptions.CreateDefault(), - isRunnablePluginFile: IsDesktop, sessionCancellationToken: new CancellationToken(canceled: true))); } @@ -145,11 +140,10 @@ public async Task GetOrCreateAsync_ThrowsIfDisposed() var exception = await Assert.ThrowsAsync( () => factory.GetOrCreateAsync( - filePath: "a", + new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop), arguments: PluginConstants.PluginArguments, requestHandlers: new RequestHandlers(), options: ConnectionOptions.CreateDefault(), - isRunnablePluginFile: IsDesktop, sessionCancellationToken: CancellationToken.None)); Assert.Equal(nameof(PluginFactory), exception.ObjectName); @@ -176,7 +170,7 @@ echo File executed > ""{outputPath}"" var pluginFactory = new PluginFactory(Timeout.InfiniteTimeSpan); // Act - var plugin = await Assert.ThrowsAnyAsync(() => pluginFactory.GetOrCreateAsync(pluginPath, args, reqHandler, options, isRunnablePluginFile: true, CancellationToken.None)); + var plugin = await Assert.ThrowsAnyAsync(() => pluginFactory.GetOrCreateAsync(new PluginFile(filePath: pluginPath, state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: false), args, reqHandler, options, CancellationToken.None)); // Assert string outputContent = File.ReadAllText(outputPath); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFileTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFileTests.cs index 40cf68cd0a0..923c44842ea 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFileTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginFileTests.cs @@ -25,7 +25,7 @@ public bool IsDesktop [InlineData("")] public void Constructor_ThrowsForNullOrEmptyFilePath(string filePath) { - var exception = Assert.Throws(() => new PluginFile(filePath, state: new Lazy(() => PluginFileState.NotFound), isRunnablePluginFile: IsDesktop)); + var exception = Assert.Throws(() => new PluginFile(filePath, state: new Lazy(() => PluginFileState.NotFound), requiresDotnetHost: !IsDesktop)); Assert.Equal("filePath", exception.ParamName); } @@ -33,7 +33,7 @@ public void Constructor_ThrowsForNullOrEmptyFilePath(string filePath) [Fact] public void Constructor_InitializesProperties() { - var pluginFile = new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop); + var pluginFile = new PluginFile(filePath: "a", state: new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop); Assert.Equal("a", pluginFile.Path); Assert.Equal(PluginFileState.Valid, pluginFile.State.Value); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs index 628b8aca43c..5a86f96ec02 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs @@ -39,11 +39,10 @@ public async Task TryGetSourceAgnosticPluginAsync_WhenExceptionIsThrownDuringPlu var exception = new Exception(message); pluginFactory.Setup(x => x.GetOrCreateAsync( - It.Is(filePath => string.Equals(filePath, PluginFilePath, StringComparison.Ordinal)), + It.Is(pluginFile => string.Equals(pluginFile.Path, PluginFilePath, StringComparison.Ordinal)), It.Is>(arguments => arguments != null && arguments.Any()), It.IsNotNull(), It.IsNotNull(), - It.IsAny(), It.IsAny())) .ThrowsAsync(exception); pluginFactory.Setup(x => x.Dispose()); @@ -58,7 +57,7 @@ public async Task TryGetSourceAgnosticPluginAsync_WhenExceptionIsThrownDuringPlu var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); Tuple result = await pluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -89,7 +88,7 @@ public async Task TryGetSourceAgnosticPluginAsync_WhenSuccessfullyCreated_Operat var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); Tuple result = await test.PluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -127,7 +126,7 @@ public async Task TryGetSourceAgnosticPluginAsync_WhenCacheFileIndicatesIndicate var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); Tuple result = await test.PluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -176,7 +175,7 @@ public async Task PluginManager_CreatePlugin_PrefersFrameworkSpecificEnvironment var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); Tuple result = await test.PluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -226,7 +225,7 @@ public async Task PluginManager_CreatePlugin_EmptyFrameworkSpecificEnvironmentVa var discoveryResult = new PluginDiscoveryResult( new PluginFile( PluginFilePath, - new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); Tuple result = await test.PluginManager.TryGetSourceAgnosticPluginAsync( discoveryResult, @@ -312,7 +311,7 @@ internal PluginManagerTest( _pluginDiscoverer.Setup(x => x.DiscoverAsync(It.IsAny())) .ReturnsAsync(new[] { - new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState), isRunnablePluginFile: IsDesktop)) + new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState), requiresDotnetHost : ! IsDesktop)) }); _connection = new Mock(MockBehavior.Strict); @@ -354,11 +353,10 @@ internal PluginManagerTest( _factory.Setup(x => x.Dispose()); _factory.Setup(x => x.GetOrCreateAsync( - It.Is(p => p == pluginFilePath), + It.Is(p => p.Path == pluginFilePath), It.IsNotNull>(), It.IsNotNull(), It.IsNotNull(), - It.IsAny(), It.IsAny())) .ReturnsAsync(_plugin.Object); diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs index bac8116dfc0..cb5daa4cbd4 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs @@ -310,7 +310,7 @@ private static IEnumerable GetPluginDiscoveryResults(stri foreach (var path in pluginPaths.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { var state = path == "a" ? PluginFileState.Valid : PluginFileState.InvalidEmbeddedSignature; - var file = new PluginFile(path, new Lazy(() => state), isRunnablePluginFile: IsDesktop); + var file = new PluginFile(path, new Lazy(() => state), requiresDotnetHost: !IsDesktop); results.Add(new PluginDiscoveryResult(file)); } @@ -377,7 +377,7 @@ internal PluginResourceProviderPositiveTest( _pluginDiscoverer.Setup(x => x.DiscoverAsync(It.IsAny())) .ReturnsAsync(new[] { - new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState), isRunnablePluginFile: IsDesktop)) + new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState), requiresDotnetHost : ! IsDesktop)) }); _connection = new Mock(MockBehavior.Strict); @@ -433,11 +433,10 @@ internal PluginResourceProviderPositiveTest( _factory.Setup(x => x.Dispose()); _factory.Setup(x => x.GetOrCreateAsync( - It.Is(p => p == pluginFilePath), + It.Is(p => p.Path == pluginFilePath), It.IsNotNull>(), It.IsNotNull(), It.IsNotNull(), - It.IsAny(), It.IsAny())) .ReturnsAsync(_plugin.Object); From ce3ff64d681427919c9909ad2c561578b45b3c3f Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Tue, 5 Nov 2024 16:24:42 -0800 Subject: [PATCH 13/16] cleanup --- .../Plugins/PluginDiscoverer.cs | 22 ++++++++++++------- .../PluginManagerMock.cs | 5 ++--- .../SecurePluginCredentialProviderTests.cs | 20 ++++++++--------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs index 5ffe1d3c97d..00c5ab489c2 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginDiscoverer.cs @@ -23,6 +23,17 @@ public sealed class PluginDiscoverer : IPluginDiscoverer private IEnumerable _results; private readonly SemaphoreSlim _semaphore; private readonly IEnvironmentVariableReader _environmentVariableReader; + private static bool IsDesktop + { + get + { +#if IS_DESKTOP + return true; +#else + return false; +#endif + } + } public PluginDiscoverer() : this(EnvironmentVariableWrapper.Instance) @@ -168,7 +179,7 @@ private static List GetPluginFiles(IEnumerable filePaths, Ca { return PluginFileState.InvalidFilePath; } - }), requiresDotnetHost: true); + }), requiresDotnetHost: !IsDesktop); files.Add(pluginFile); } @@ -182,11 +193,6 @@ private static List GetPluginFiles(IEnumerable filePaths, Ca /// A list of valid objects representing the discovered plugins. internal List GetPluginsInNuGetPluginPaths() { - bool isDesktop = false; - -#if IS_DESKTOP - isDesktop = true; -#endif var pluginFiles = new List(); string[] paths = _nuGetPluginPaths?.Split(Path.PathSeparator) ?? Array.Empty(); @@ -210,7 +216,7 @@ internal List GetPluginsInNuGetPluginPaths() { // A non DotNet tool plugin file var state = new Lazy(() => PluginFileState.Valid); - pluginFiles.Add(new PluginFile(fileInfo.FullName, state, requiresDotnetHost: !isDesktop)); + pluginFiles.Add(new PluginFile(fileInfo.FullName, state, requiresDotnetHost: !IsDesktop)); } } else if (Directory.Exists(path)) @@ -220,7 +226,7 @@ internal List GetPluginsInNuGetPluginPaths() } else { - pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath), requiresDotnetHost: !isDesktop)); + pluginFiles.Add(new PluginFile(path, new Lazy(() => PluginFileState.InvalidFilePath), requiresDotnetHost: !IsDesktop)); } } diff --git a/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs b/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs index 90f50603331..c53e2dfdeb9 100644 --- a/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs +++ b/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs @@ -250,7 +250,7 @@ private void EnsureDiscovererIsCalled(string pluginFilePath, PluginFileState plu _pluginDiscoverer.Setup(x => x.DiscoverAsync(It.IsAny())) .ReturnsAsync(new[] { - new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState), isRunnablePluginFile: IsDesktop)) + new PluginDiscoveryResult(new PluginFile(pluginFilePath, new Lazy(() => pluginFileState), requiresDotnetHost: !IsDesktop)) }); } @@ -293,11 +293,10 @@ private void EnsureFactorySetupCalls(string pluginFilePath) { _factory.Setup(x => x.Dispose()); _factory.Setup(x => x.GetOrCreateAsync( - It.Is(p => p == pluginFilePath), + It.Is(p => p.Path == pluginFilePath), It.IsNotNull>(), It.IsNotNull(), It.IsNotNull(), - It.IsAny(), It.IsAny())) .ReturnsAsync(_plugin.Object); } diff --git a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs index aa003ceff16..c790ab5928f 100644 --- a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs @@ -106,7 +106,7 @@ public async Task GetAsync_WithValidArguments_ReturnsValidCredentials() pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -141,7 +141,7 @@ public async Task GetAsync_WhenCalledMultipleTimes_DoesNotCreateMultipleInstance pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -178,7 +178,7 @@ public async Task GetAsync_WhenPluginClaimsMultipleOperations_ReturnsValidCreden pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -218,7 +218,7 @@ public async Task GetAsync_WhenProxyIsUsed_SetsProxyCredentials() pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); var proxy = new System.Net.WebProxy() { @@ -255,7 +255,7 @@ public async Task GetAsync_WhenCalledMultipleTimes_CachesCapabilities() pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -285,7 +285,7 @@ public async Task GetAsync_WhenCalledMultipleTimes_CachesCapabilities() pluginFileState: PluginFileState.Valid, expectations: expectations2)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -323,7 +323,7 @@ public async Task GetAsync_SendsCorrectCanShowDialogValue() pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -356,7 +356,7 @@ public async Task GetAsync_WhenPluginManagerReturnsException_ExceptionIsPropagat It.IsAny())) .ReturnsAsync(result); - var pluginDiscoveryResult = new PluginDiscoveryResult(new PluginFile("c", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + var pluginDiscoveryResult = new PluginDiscoveryResult(new PluginFile("c", new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); var logger = new Mock(MockBehavior.Strict); logger.Setup(x => x.LogError(It.Is(data => data == expectedMessage))); @@ -391,7 +391,7 @@ public async Task GetAsync_WhenCredentialPluginIsUnableToAcquireCredentials_Retu pluginFileState: PluginFileState.Valid, expectations: expectation)) { - var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), isRunnablePluginFile: IsDesktop)); + var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy(() => PluginFileState.Valid), requiresDotnetHost: !IsDesktop)); var provider = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance); IWebProxy proxy = null; @@ -409,7 +409,7 @@ public async Task GetAsync_WhenCredentialPluginIsUnableToAcquireCredentials_Retu private PluginDiscoveryResult CreatePluginDiscoveryResult(PluginFileState pluginState = PluginFileState.Valid) { - return new PluginDiscoveryResult(new PluginFile(Path.Combine(_testDirectory.Path, "plugin.exe"), new Lazy(() => pluginState), isRunnablePluginFile: IsDesktop)); + return new PluginDiscoveryResult(new PluginFile(Path.Combine(_testDirectory.Path, "plugin.exe"), new Lazy(() => pluginState), requiresDotnetHost: !IsDesktop)); } private PluginManager CreateDefaultPluginManager() From ea62aabfcf856100abefbceb26707beace223ae3 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Tue, 5 Nov 2024 16:26:00 -0800 Subject: [PATCH 14/16] cleanup --- .../SecurePluginCredentialProviderBuilderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs index 88970d78a1a..abe2e144fb4 100644 --- a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs @@ -181,7 +181,7 @@ private static IEnumerable GetPluginDiscoveryResults(List var results = new List(); foreach (var plugin in plugins) { - var file = new PluginFile(plugin.Key, new Lazy(() => plugin.Value), isRunnablePluginFile: IsDesktop); + var file = new PluginFile(plugin.Key, new Lazy(() => plugin.Value), requiresDotnetHost: !IsDesktop); results.Add(new PluginDiscoveryResult(file)); } From b7a1a0450544fa18bccbae8b93be41ea5844e324 Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Wed, 6 Nov 2024 10:33:38 -0800 Subject: [PATCH 15/16] Unexpose IpluginFactory Api --- src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs | 2 +- src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs | 2 +- .../NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt | 2 -- .../NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt | 2 +- .../NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt | 2 -- .../NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt | 2 +- .../PublicAPI/netstandard2.0/PublicAPI.Shipped.txt | 2 -- .../PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt | 2 +- .../NuGet.Credentials.Test/PluginManagerMock.cs | 4 ++-- .../SecurePluginCredentialProviderBuilderTests.cs | 4 ++-- .../SecurePluginCredentialProviderTests.cs | 2 +- .../NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs | 6 +++--- .../Plugins/PluginResourceProviderTests.cs | 6 +++--- 13 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs index 4509749111d..1c5b0f3c697 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/IPluginFactory.cs @@ -11,7 +11,7 @@ namespace NuGet.Protocol.Plugins /// /// A plugin factory. /// - public interface IPluginFactory : IDisposable + internal interface IPluginFactory : IDisposable { /// /// Asynchronously gets an existing plugin instance or creates a new instance and connects to it. diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs index c3a9a34a818..11acfc56c71 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginManager.cs @@ -55,7 +55,7 @@ private PluginManager() public PluginManager( IEnvironmentVariableReader reader, Lazy pluginDiscoverer, - Func pluginFactoryCreator, + Func pluginFactoryCreator, Lazy pluginsCacheDirectoryPath) { Initialize( diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt index 4043f67eccf..2b22211a890 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt @@ -1015,7 +1015,6 @@ NuGet.Protocol.Plugins.IPlugin.Closed -> System.EventHandler ~NuGet.Protocol.Plugins.IPlugin.Name.get -> string NuGet.Protocol.Plugins.IPluginDiscoverer ~NuGet.Protocol.Plugins.IPluginDiscoverer.DiscoverAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> -NuGet.Protocol.Plugins.IPluginFactory NuGet.Protocol.Plugins.IPluginManager ~NuGet.Protocol.Plugins.IPluginManager.CreatePluginsAsync(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> ~NuGet.Protocol.Plugins.IPluginManager.FindAvailablePluginsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> @@ -1225,7 +1224,6 @@ NuGet.Protocol.Plugins.PluginManager NuGet.Protocol.Plugins.PluginManager.Dispose() -> void ~NuGet.Protocol.Plugins.PluginManager.EnvironmentVariableReader.get -> NuGet.Common.IEnvironmentVariableReader ~NuGet.Protocol.Plugins.PluginManager.FindAvailablePluginsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> -~NuGet.Protocol.Plugins.PluginManager.PluginManager(NuGet.Common.IEnvironmentVariableReader reader, System.Lazy pluginDiscoverer, System.Func pluginFactoryCreator, System.Lazy pluginsCacheDirectoryPath) -> void ~NuGet.Protocol.Plugins.PluginManager.TryGetSourceAgnosticPluginAsync(NuGet.Protocol.Plugins.PluginDiscoveryResult pluginDiscoveryResult, NuGet.Protocol.Plugins.OperationClaim requestedOperationClaim, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> NuGet.Protocol.Plugins.PluginMulticlientUtilities ~NuGet.Protocol.Plugins.PluginMulticlientUtilities.DoOncePerPluginLifetimeAsync(string key, System.Func taskFunc, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt index 1507646b1ff..71559b77737 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task ~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task ~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool requiresDotnetHost) -> void +~NuGet.Protocol.Plugins.PluginManager.PluginManager(NuGet.Common.IEnvironmentVariableReader reader, System.Lazy pluginDiscoverer, System.Func pluginFactoryCreator, System.Lazy pluginsCacheDirectoryPath) -> void diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt index fbc3dca5680..1560c232cd2 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt @@ -1015,7 +1015,6 @@ NuGet.Protocol.Plugins.IPlugin.Closed -> System.EventHandler ~NuGet.Protocol.Plugins.IPlugin.Name.get -> string NuGet.Protocol.Plugins.IPluginDiscoverer ~NuGet.Protocol.Plugins.IPluginDiscoverer.DiscoverAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> -NuGet.Protocol.Plugins.IPluginFactory NuGet.Protocol.Plugins.IPluginManager ~NuGet.Protocol.Plugins.IPluginManager.CreatePluginsAsync(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> ~NuGet.Protocol.Plugins.IPluginManager.FindAvailablePluginsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> @@ -1225,7 +1224,6 @@ NuGet.Protocol.Plugins.PluginManager NuGet.Protocol.Plugins.PluginManager.Dispose() -> void ~NuGet.Protocol.Plugins.PluginManager.EnvironmentVariableReader.get -> NuGet.Common.IEnvironmentVariableReader ~NuGet.Protocol.Plugins.PluginManager.FindAvailablePluginsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> -~NuGet.Protocol.Plugins.PluginManager.PluginManager(NuGet.Common.IEnvironmentVariableReader reader, System.Lazy pluginDiscoverer, System.Func pluginFactoryCreator, System.Lazy pluginsCacheDirectoryPath) -> void ~NuGet.Protocol.Plugins.PluginManager.TryGetSourceAgnosticPluginAsync(NuGet.Protocol.Plugins.PluginDiscoveryResult pluginDiscoveryResult, NuGet.Protocol.Plugins.OperationClaim requestedOperationClaim, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> NuGet.Protocol.Plugins.PluginMulticlientUtilities ~NuGet.Protocol.Plugins.PluginMulticlientUtilities.DoOncePerPluginLifetimeAsync(string key, System.Func taskFunc, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt index 1507646b1ff..71559b77737 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task ~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task ~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool requiresDotnetHost) -> void +~NuGet.Protocol.Plugins.PluginManager.PluginManager(NuGet.Common.IEnvironmentVariableReader reader, System.Lazy pluginDiscoverer, System.Func pluginFactoryCreator, System.Lazy pluginsCacheDirectoryPath) -> void diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt index fbc3dca5680..1560c232cd2 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt @@ -1015,7 +1015,6 @@ NuGet.Protocol.Plugins.IPlugin.Closed -> System.EventHandler ~NuGet.Protocol.Plugins.IPlugin.Name.get -> string NuGet.Protocol.Plugins.IPluginDiscoverer ~NuGet.Protocol.Plugins.IPluginDiscoverer.DiscoverAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> -NuGet.Protocol.Plugins.IPluginFactory NuGet.Protocol.Plugins.IPluginManager ~NuGet.Protocol.Plugins.IPluginManager.CreatePluginsAsync(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> ~NuGet.Protocol.Plugins.IPluginManager.FindAvailablePluginsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> @@ -1225,7 +1224,6 @@ NuGet.Protocol.Plugins.PluginManager NuGet.Protocol.Plugins.PluginManager.Dispose() -> void ~NuGet.Protocol.Plugins.PluginManager.EnvironmentVariableReader.get -> NuGet.Common.IEnvironmentVariableReader ~NuGet.Protocol.Plugins.PluginManager.FindAvailablePluginsAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> -~NuGet.Protocol.Plugins.PluginManager.PluginManager(NuGet.Common.IEnvironmentVariableReader reader, System.Lazy pluginDiscoverer, System.Func pluginFactoryCreator, System.Lazy pluginsCacheDirectoryPath) -> void ~NuGet.Protocol.Plugins.PluginManager.TryGetSourceAgnosticPluginAsync(NuGet.Protocol.Plugins.PluginDiscoveryResult pluginDiscoveryResult, NuGet.Protocol.Plugins.OperationClaim requestedOperationClaim, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> NuGet.Protocol.Plugins.PluginMulticlientUtilities ~NuGet.Protocol.Plugins.PluginMulticlientUtilities.DoOncePerPluginLifetimeAsync(string key, System.Func taskFunc, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 1507646b1ff..71559b77737 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,5 +1,5 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.IPluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task ~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task ~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool requiresDotnetHost) -> void +~NuGet.Protocol.Plugins.PluginManager.PluginManager(NuGet.Common.IEnvironmentVariableReader reader, System.Lazy pluginDiscoverer, System.Func pluginFactoryCreator, System.Lazy pluginsCacheDirectoryPath) -> void diff --git a/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs b/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs index c53e2dfdeb9..ce13791271e 100644 --- a/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs +++ b/test/NuGet.Core.Tests/NuGet.Credentials.Test/PluginManagerMock.cs @@ -80,7 +80,7 @@ public static bool IsDesktop private readonly Mock _connection; private readonly TestExpectation _expectations; - private readonly Mock _factory; + private readonly Mock _factory; private readonly Mock _plugin; private readonly Mock _pluginDiscoverer; private readonly Mock _reader; @@ -111,7 +111,7 @@ internal PluginManagerMock( _plugin = new Mock(MockBehavior.Strict); EnsurePluginSetupCalls(); - _factory = new Mock(MockBehavior.Strict); + _factory = new Mock(MockBehavior.Strict); EnsureFactorySetupCalls(pluginFilePath); // Setup connection diff --git a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs index abe2e144fb4..49d868ff7cd 100644 --- a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderBuilderTests.cs @@ -167,7 +167,7 @@ internal PluginManagerBuilderMock(List> pl PluginManager = new PluginManager( reader.Object, new Lazy(() => pluginDiscoverer.Object), - (TimeSpan idleTimeout) => Mock.Of(), + (TimeSpan idleTimeout) => Mock.Of(), new Lazy(() => _testDirectory.Path)); } @@ -194,7 +194,7 @@ private PluginManager CreateDefaultPluginManager() return new PluginManager( Mock.Of(), new Lazy(), - (TimeSpan idleTimeout) => Mock.Of(), + (TimeSpan idleTimeout) => Mock.Of(), new Lazy(() => _testDirectory.Path)); } } diff --git a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs index c790ab5928f..d17d61c3c81 100644 --- a/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Credentials.Test/SecurePluginCredentialProviderTests.cs @@ -417,7 +417,7 @@ private PluginManager CreateDefaultPluginManager() return new PluginManager( Mock.Of(), new Lazy(), - (TimeSpan idleTimeout) => Mock.Of(), + (TimeSpan idleTimeout) => Mock.Of(), new Lazy(() => _testDirectory.Path)); } diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs index 5a86f96ec02..230227c289f 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginManagerTests.cs @@ -35,7 +35,7 @@ public async Task TryGetSourceAgnosticPluginAsync_WhenExceptionIsThrownDuringPlu const string message = "b"; var reader = Mock.Of(); - var pluginFactory = new Mock(MockBehavior.Strict); + var pluginFactory = new Mock(MockBehavior.Strict); var exception = new Exception(message); pluginFactory.Setup(x => x.GetOrCreateAsync( @@ -259,7 +259,7 @@ public bool IsDesktop } } private readonly Mock _connection; - private readonly Mock _factory; + private readonly Mock _factory; private readonly Mock _plugin; private readonly Mock _pluginDiscoverer; private readonly Mock _reader; @@ -349,7 +349,7 @@ internal PluginManagerTest( _plugin.SetupGet(x => x.Id) .Returns("id"); - _factory = new Mock(MockBehavior.Strict); + _factory = new Mock(MockBehavior.Strict); _factory.Setup(x => x.Dispose()); _factory.Setup(x => x.GetOrCreateAsync( diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs index cb5daa4cbd4..d4661dc82f4 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/PluginResourceProviderTests.cs @@ -284,7 +284,7 @@ internal PluginResourceProviderNegativeTest(string serviceIndexJson, string sour _pluginManager = new PluginManager( _environmentVariableReader.Object, new Lazy(() => _pluginDiscoverer.Object), - (TimeSpan idleTimeout) => Mock.Of(), + (TimeSpan idleTimeout) => Mock.Of(), new Lazy(() => _testDirectory.Path)); Provider = new PluginResourceProvider(_pluginManager); } @@ -333,7 +333,7 @@ public static bool IsDesktop } private readonly Mock _connection; private readonly IEnumerable _expectations; - private readonly Mock _factory; + private readonly Mock _factory; private readonly Mock _plugin; private readonly Mock _pluginDiscoverer; private readonly Mock _reader; @@ -429,7 +429,7 @@ internal PluginResourceProviderPositiveTest( _plugin.SetupGet(x => x.Id) .Returns("id"); - _factory = new Mock(MockBehavior.Strict); + _factory = new Mock(MockBehavior.Strict); _factory.Setup(x => x.Dispose()); _factory.Setup(x => x.GetOrCreateAsync( From 818ebd490a6f60107c0a0bb951225802f404b2bf Mon Sep 17 00:00:00 2001 From: Nigusu Yenework Date: Wed, 6 Nov 2024 11:58:33 -0800 Subject: [PATCH 16/16] make PluginFactory mockable --- src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs | 8 +++++--- .../NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt | 1 - .../PublicAPI/net472/PublicAPI.Unshipped.txt | 3 ++- .../NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt | 1 - .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 3 ++- .../PublicAPI/netstandard2.0/PublicAPI.Shipped.txt | 1 - .../PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt | 3 ++- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs index 1915bc8714d..4034c79086c 100644 --- a/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs +++ b/src/NuGet.Core/NuGet.Protocol/Plugins/PluginFactory.cs @@ -17,13 +17,15 @@ namespace NuGet.Protocol.Plugins /// /// A plugin factory. /// - public sealed class PluginFactory : IPluginFactory + public class PluginFactory : IPluginFactory { private bool _isDisposed; private readonly IPluginLogger _logger; private readonly TimeSpan _pluginIdleTimeout; private readonly ConcurrentDictionary>> _plugins; + internal PluginFactory() { } + /// /// Instantiates a new class. /// @@ -48,7 +50,7 @@ public PluginFactory(TimeSpan pluginIdleTimeout) /// /// Disposes of this instance. /// - public void Dispose() + public virtual void Dispose() { if (_isDisposed) { @@ -99,7 +101,7 @@ public void Dispose() /// Thrown if a plugin protocol error occurs. /// Thrown for a plugin failure during creation. /// This is intended to be called by NuGet client tools. - public async Task GetOrCreateAsync( + public virtual async Task GetOrCreateAsync( PluginFile pluginFile, IEnumerable arguments, IRequestHandlers requestHandlers, diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt index 2b22211a890..d17e6c22f10 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt @@ -1209,7 +1209,6 @@ NuGet.Protocol.Plugins.PluginException ~NuGet.Protocol.Plugins.PluginException.PluginException(string message) -> void ~NuGet.Protocol.Plugins.PluginException.PluginException(string message, System.Exception innerException) -> void NuGet.Protocol.Plugins.PluginFactory -NuGet.Protocol.Plugins.PluginFactory.Dispose() -> void NuGet.Protocol.Plugins.PluginFactory.PluginFactory(System.TimeSpan pluginIdleTimeout) -> void NuGet.Protocol.Plugins.PluginFile ~NuGet.Protocol.Plugins.PluginFile.Path.get -> string diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt index 71559b77737..deb1138c126 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,5 +1,6 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +virtual NuGet.Protocol.Plugins.PluginFactory.Dispose() -> void ~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool requiresDotnetHost) -> void ~NuGet.Protocol.Plugins.PluginManager.PluginManager(NuGet.Common.IEnvironmentVariableReader reader, System.Lazy pluginDiscoverer, System.Func pluginFactoryCreator, System.Lazy pluginsCacheDirectoryPath) -> void +~virtual NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt index 1560c232cd2..07c3e1d7c43 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt @@ -1209,7 +1209,6 @@ NuGet.Protocol.Plugins.PluginException ~NuGet.Protocol.Plugins.PluginException.PluginException(string message) -> void ~NuGet.Protocol.Plugins.PluginException.PluginException(string message, System.Exception innerException) -> void NuGet.Protocol.Plugins.PluginFactory -NuGet.Protocol.Plugins.PluginFactory.Dispose() -> void NuGet.Protocol.Plugins.PluginFactory.PluginFactory(System.TimeSpan pluginIdleTimeout) -> void NuGet.Protocol.Plugins.PluginFile ~NuGet.Protocol.Plugins.PluginFile.Path.get -> string diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt index 71559b77737..deb1138c126 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -1,5 +1,6 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +virtual NuGet.Protocol.Plugins.PluginFactory.Dispose() -> void ~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool requiresDotnetHost) -> void ~NuGet.Protocol.Plugins.PluginManager.PluginManager(NuGet.Common.IEnvironmentVariableReader reader, System.Lazy pluginDiscoverer, System.Func pluginFactoryCreator, System.Lazy pluginsCacheDirectoryPath) -> void +~virtual NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt index 1560c232cd2..07c3e1d7c43 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt @@ -1209,7 +1209,6 @@ NuGet.Protocol.Plugins.PluginException ~NuGet.Protocol.Plugins.PluginException.PluginException(string message) -> void ~NuGet.Protocol.Plugins.PluginException.PluginException(string message, System.Exception innerException) -> void NuGet.Protocol.Plugins.PluginFactory -NuGet.Protocol.Plugins.PluginFactory.Dispose() -> void NuGet.Protocol.Plugins.PluginFactory.PluginFactory(System.TimeSpan pluginIdleTimeout) -> void NuGet.Protocol.Plugins.PluginFile ~NuGet.Protocol.Plugins.PluginFile.Path.get -> string diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 71559b77737..deb1138c126 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,5 +1,6 @@ #nullable enable NuGet.Protocol.Plugins.PluginDiscoverer.PluginDiscoverer() -> void -~NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task +virtual NuGet.Protocol.Plugins.PluginFactory.Dispose() -> void ~NuGet.Protocol.Plugins.PluginFile.PluginFile(string filePath, System.Lazy state, bool requiresDotnetHost) -> void ~NuGet.Protocol.Plugins.PluginManager.PluginManager(NuGet.Common.IEnvironmentVariableReader reader, System.Lazy pluginDiscoverer, System.Func pluginFactoryCreator, System.Lazy pluginsCacheDirectoryPath) -> void +~virtual NuGet.Protocol.Plugins.PluginFactory.GetOrCreateAsync(NuGet.Protocol.Plugins.PluginFile pluginFile, System.Collections.Generic.IEnumerable arguments, NuGet.Protocol.Plugins.IRequestHandlers requestHandlers, NuGet.Protocol.Plugins.ConnectionOptions options, System.Threading.CancellationToken sessionCancellationToken) -> System.Threading.Tasks.Task