From d607ba585b7dfe74fa53d25f71031e660d71822f Mon Sep 17 00:00:00 2001 From: Charlie Poole Date: Mon, 21 Oct 2024 16:43:37 -0700 Subject: [PATCH] Implement an algorithm to find extensions --- GitVersion.yml | 2 +- NUnitConsole.sln | 10 +--- build.cake | 36 ++++++----- nuget/engine/nunit.agent.addins | 1 - nuget/engine/nunit.engine.nuget.addins | 4 -- nuget/engine/nunit.engine.nuspec | 6 -- nuget/runners/net8.0/DotnetToolSettings.xml | 6 -- .../runners/nunit.console-runner.net80.nuspec | 53 ----------------- .../nunit.console-runner.netcore.nuspec | 1 - nuget/runners/nunit.console-runner.nuspec | 6 -- nuget/runners/nunit.console.nuget.addins | 11 ---- .../runners/nunit.console.nuget.agent.addins | 11 ---- package-tests.cake | 2 +- .../Services/ExtensionManagerTests.cs | 4 +- .../Services/ExtensionManager.cs | 59 ++++++++++++++++--- .../Services/ExtensionService.cs | 14 ++++- .../Services/IExtensionManager.cs | 17 +++++- 17 files changed, 104 insertions(+), 139 deletions(-) delete mode 100644 nuget/engine/nunit.agent.addins delete mode 100644 nuget/engine/nunit.engine.nuget.addins delete mode 100644 nuget/runners/net8.0/DotnetToolSettings.xml delete mode 100644 nuget/runners/nunit.console-runner.net80.nuspec delete mode 100644 nuget/runners/nunit.console.nuget.addins delete mode 100644 nuget/runners/nunit.console.nuget.agent.addins diff --git a/GitVersion.yml b/GitVersion.yml index 19dfb1105..3b27dee15 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,4 +1,4 @@ -next-version: 3.18.0 +next-version: 3.19.0 mode: ContinuousDelivery legacy-semver-padding: 5 build-metadata-padding: 5 diff --git a/NUnitConsole.sln b/NUnitConsole.sln index 9b322fbb5..8702696b9 100644 --- a/NUnitConsole.sln +++ b/NUnitConsole.sln @@ -77,8 +77,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "choco", "choco", "{4FDF7BFA choco\nunit-agent-x86.exe.ignore = choco\nunit-agent-x86.exe.ignore choco\nunit-agent.exe.ignore = choco\nunit-agent.exe.ignore choco\nunit-console-runner.nuspec = choco\nunit-console-runner.nuspec - choco\nunit.console.choco.addins = choco\nunit.console.choco.addins - choco\nunit.console.choco.agent.addins = choco\nunit.console.choco.agent.addins choco\VERIFICATION.txt = choco\VERIFICATION.txt EndProjectSection EndProject @@ -147,14 +145,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InvalidTestNames", "src\Tes EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppContextTest", "src\TestData\AppContextTest\AppContextTest.csproj", "{E43A3E4B-B050-471B-B43C-0DF60FD44376}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "net8.0", "net8.0", "{303CF83E-2A87-4882-8CAC-3EB59AAD81FC}" - ProjectSection(SolutionItems) = preProject - nuget\runners\net8.0\DotnetToolSettings.xml = nuget\runners\net8.0\DotnetToolSettings.xml - EndProjectSection -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mock-assembly-v2", "src\TestData\mock-assembly-v2\mock-assembly-v2.csproj", "{AD40CA55-35CC-41CA-85F5-8FDA4ECAFF78}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FakeExtensions", "src\TestData\FakeExtensions\FakeExtensions.csproj", "{D6C217E0-BFB7-4C80-8D50-C969F46EBC59}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FakeExtensions", "src\TestData\FakeExtensions\FakeExtensions.csproj", "{D6C217E0-BFB7-4C80-8D50-C969F46EBC59}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -276,7 +269,6 @@ Global {6B550F25-1CA5-4F3E-B631-1ECCD4CB94E4} = {2ECE1CFB-9436-4149-B7E4-1FB1786FDE9F} {58E18ACC-1F7E-4395-817E-E7EF943E0C77} = {2ECE1CFB-9436-4149-B7E4-1FB1786FDE9F} {E43A3E4B-B050-471B-B43C-0DF60FD44376} = {2ECE1CFB-9436-4149-B7E4-1FB1786FDE9F} - {303CF83E-2A87-4882-8CAC-3EB59AAD81FC} = {F3E87D0F-6F06-4C0B-AE06-42C0834C3C6E} {AD40CA55-35CC-41CA-85F5-8FDA4ECAFF78} = {2ECE1CFB-9436-4149-B7E4-1FB1786FDE9F} {D6C217E0-BFB7-4C80-8D50-C969F46EBC59} = {2ECE1CFB-9436-4149-B7E4-1FB1786FDE9F} EndGlobalSection diff --git a/build.cake b/build.cake index d6377ab16..9005688f2 100644 --- a/build.cake +++ b/build.cake @@ -19,7 +19,7 @@ BuildSettings.Initialize( FilePath[] ConsoleFiles = { "nunit3-console.dll", "nunit3-console.dll.config", "nunit3-console.exe", "nunit3-console.pdb", - "nunit3-console.deps.json", "nunit3-console.runtimeconfig.json", "nunit.console.nuget.addins" }; + "nunit3-console.deps.json", "nunit3-console.runtimeconfig.json" }; FilePath[] ENGINE_FILES = { "nunit.engine.dll", "nunit.engine.core.dll", "nunit.engine.api.dll", "testcentric.engine.metadata.dll" }; FilePath[] ENGINE_PDB_FILES = { @@ -61,12 +61,12 @@ BuildSettings.Packages.AddRange(new PackageDefinition[] { source: BuildSettings.NuGetDirectory + "runners/nunit.console-runner.nuspec", checks: new PackageCheck[] { HasFiles("LICENSE.txt", "NOTICES.txt"), - HasDirectory("tools").WithFiles("nunit3-console.exe", "nunit3-console.exe.config", "nunit.console.nuget.addins").AndFiles(ENGINE_FILES), - HasDirectory("tools/agents/net462").WithFiles(AGENT_FILES).AndFile("nunit.console.nuget.agent.addins"), - HasDirectory("tools/agents/netcoreapp3.1").WithFiles(AGENT_FILES_NETCORE).AndFile("nunit.console.nuget.agent.addins"), - HasDirectory("tools/agents/net6.0").WithFiles(AGENT_FILES_NETCORE).AndFile("nunit.console.nuget.agent.addins"), - HasDirectory("tools/agents/net7.0").WithFiles(AGENT_FILES_NETCORE).AndFile("nunit.console.nuget.agent.addins"), - HasDirectory("tools/agents/net8.0").WithFiles(AGENT_FILES_NETCORE).AndFile("nunit.console.nuget.agent.addins") + HasDirectory("tools").WithFiles("nunit3-console.exe", "nunit3-console.exe.config").AndFiles(ENGINE_FILES), + HasDirectory("tools/agents/net462").WithFiles(AGENT_FILES), + HasDirectory("tools/agents/netcoreapp3.1").WithFiles(AGENT_FILES_NETCORE), + HasDirectory("tools/agents/net6.0").WithFiles(AGENT_FILES_NETCORE), + HasDirectory("tools/agents/net7.0").WithFiles(AGENT_FILES_NETCORE), + HasDirectory("tools/agents/net8.0").WithFiles(AGENT_FILES_NETCORE) }, symbols: new PackageCheck[] { HasDirectory("tools").WithFiles(ENGINE_PDB_FILES).AndFile("nunit3-console.pdb"), @@ -103,12 +103,12 @@ BuildSettings.Packages.AddRange(new PackageDefinition[] { id: "nunit-console-runner", source: BuildSettings.ChocolateyDirectory + "nunit-console-runner.nuspec", checks: new PackageCheck[] { - HasDirectory("tools").WithFiles("LICENSE.txt", "NOTICES.txt", "VERIFICATION.txt", "nunit3-console.exe", "nunit3-console.exe.config", "nunit.console.choco.addins").AndFiles(ENGINE_FILES), - HasDirectory("tools/agents/net462").WithFiles(AGENT_FILES).AndFile("nunit.console.choco.agent.addins"), - HasDirectory("tools/agents/netcoreapp3.1").WithFiles(AGENT_FILES_NETCORE).AndFile("nunit.console.choco.agent.addins"), - HasDirectory("tools/agents/net6.0").WithFiles(AGENT_FILES_NETCORE).AndFile("nunit.console.choco.agent.addins"), - HasDirectory("tools/agents/net7.0").WithFiles(AGENT_FILES_NETCORE).AndFile("nunit.console.choco.agent.addins"), - HasDirectory("tools/agents/net8.0").WithFiles(AGENT_FILES_NETCORE).AndFile("nunit.console.choco.agent.addins") + HasDirectory("tools").WithFiles("LICENSE.txt", "NOTICES.txt", "VERIFICATION.txt", "nunit3-console.exe", "nunit3-console.exe.config").AndFiles(ENGINE_FILES), + HasDirectory("tools/agents/net462").WithFiles(AGENT_FILES), + HasDirectory("tools/agents/netcoreapp3.1").WithFiles(AGENT_FILES_NETCORE), + HasDirectory("tools/agents/net6.0").WithFiles(AGENT_FILES_NETCORE), + HasDirectory("tools/agents/net7.0").WithFiles(AGENT_FILES_NETCORE), + HasDirectory("tools/agents/net8.0").WithFiles(AGENT_FILES_NETCORE) }, testRunner: new ConsoleRunnerSelfTester(BuildSettings.ChocolateyTestDirectory + $"nunit-console-runner.{BuildSettings.PackageVersion}/tools/nunit3-console.exe"), @@ -151,9 +151,7 @@ BuildSettings.Packages.AddRange(new PackageDefinition[] { HasFiles("LICENSE.txt", "NOTICES.txt"), HasDirectory("lib/net462").WithFiles(ENGINE_FILES), HasDirectory("lib/net8.0").WithFiles(ENGINE_FILES).AndFile("Microsoft.Extensions.DependencyModel.dll"), - HasDirectory("contentFiles/any/lib/net462").WithFile("nunit.engine.nuget.addins"), - HasDirectory("contentFiles/any/lib/net8.0").WithFile("nunit.engine.nuget.addins"), - HasDirectory("contentFiles/any/agents/net462").WithFiles(AGENT_FILES).AndFile("nunit.agent.addins") + HasDirectory("contentFiles/any/agents/net462").WithFiles(AGENT_FILES) }, symbols: new PackageCheck[] { HasDirectory("lib/net462").WithFiles(ENGINE_PDB_FILES), @@ -201,6 +199,12 @@ Task("TestZipPackage") NUnitConsoleZipPackage.RunPackageTests(); }); +Task("TestNetCorePackage") + .Does(() => + { + NUnitConsoleRunnerNetCorePackage.RunPackageTests(); + }); + // Adhoc code to check content of a dotnet standalone executable // TODO: Incorporate this in the recipe itself diff --git a/nuget/engine/nunit.agent.addins b/nuget/engine/nunit.agent.addins deleted file mode 100644 index 1558d5f75..000000000 --- a/nuget/engine/nunit.agent.addins +++ /dev/null @@ -1 +0,0 @@ -../../ # refer to the directory containing the engine and runner diff --git a/nuget/engine/nunit.engine.nuget.addins b/nuget/engine/nunit.engine.nuget.addins deleted file mode 100644 index ffb7ae1b7..000000000 --- a/nuget/engine/nunit.engine.nuget.addins +++ /dev/null @@ -1,4 +0,0 @@ -../../../NUnit.Extension.*/**/tools/ # nuget v2 layout -../../../../NUnit.Extension.*/**/tools/ # nuget v3 layout -../../../nunit.extension.*/**/tools/ # nuget v2 layout -../../../../nunit.extension.*/**/tools/ # nuget v3 layout diff --git a/nuget/engine/nunit.engine.nuspec b/nuget/engine/nunit.engine.nuspec index e3eed7538..76dfd2651 100644 --- a/nuget/engine/nunit.engine.nuspec +++ b/nuget/engine/nunit.engine.nuspec @@ -66,11 +66,6 @@ - - - - - @@ -79,7 +74,6 @@ - diff --git a/nuget/runners/net8.0/DotnetToolSettings.xml b/nuget/runners/net8.0/DotnetToolSettings.xml deleted file mode 100644 index e49f98228..000000000 --- a/nuget/runners/net8.0/DotnetToolSettings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/nuget/runners/nunit.console-runner.net80.nuspec b/nuget/runners/nunit.console-runner.net80.nuspec deleted file mode 100644 index 00b997e5b..000000000 --- a/nuget/runners/nunit.console-runner.net80.nuspec +++ /dev/null @@ -1,53 +0,0 @@ - - - - NUnit.ConsoleRunner.Net80 - NUnit Console Runner (.NET 8.0) - $version$ - Charlie Poole, Rob Prouse - Charlie Poole, Rob Prouse - LICENSE.txt - https://nunit.org - - https://cdn.rawgit.com/nunit/resources/master/images/icon/nunit_256.png - images\nunit_256.png - false - .NET Core build of the console runner for the NUnit unit-testing framework. - - This package includes the .NET 8.0 build of the NUnit console runner and test engine. - - Any extensions, if needed, may be installed as separate packages. - - https://docs.nunit.org/articles/nunit/release-notes/console-and-engine.html - en-US - nunit test testing tdd runner - Copyright (c) 2021-2024 Charlie Poole, Rob Prouse - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/nuget/runners/nunit.console-runner.netcore.nuspec b/nuget/runners/nunit.console-runner.netcore.nuspec index a2005cdec..d1aa3df2b 100644 --- a/nuget/runners/nunit.console-runner.netcore.nuspec +++ b/nuget/runners/nunit.console-runner.netcore.nuspec @@ -45,7 +45,6 @@ - diff --git a/nuget/runners/nunit.console-runner.nuspec b/nuget/runners/nunit.console-runner.nuspec index 343dc1c81..3489e8a10 100644 --- a/nuget/runners/nunit.console-runner.nuspec +++ b/nuget/runners/nunit.console-runner.nuspec @@ -39,7 +39,6 @@ - @@ -53,7 +52,6 @@ - @@ -67,7 +65,6 @@ - @@ -81,7 +78,6 @@ - @@ -95,7 +91,6 @@ - @@ -108,7 +103,6 @@ - diff --git a/nuget/runners/nunit.console.nuget.addins b/nuget/runners/nunit.console.nuget.addins deleted file mode 100644 index f540c8540..000000000 --- a/nuget/runners/nunit.console.nuget.addins +++ /dev/null @@ -1,11 +0,0 @@ -# Extensions built for a single runtime target -../../NUnit.Extension.*/**/tools/ # nuget v2 layout -../../../NUnit.Extension.*/**/tools/ # nuget v3 layout -../../nunit.extension.*/**/tools/ # nuget v2 layout -../../../nunit.extension.*/**/tools/ # nuget v3 layout - -# Extensions built for multiple targets -../../NUnit.Extension.*/**/tools/*/ # nuget v2 layout -../../../NUnit.Extension.*/**/tools/*/ # nuget v3 layout -../../nunit.extension.*/**/tools/*/ # nuget v2 layout -../../../nunit.extension.*/**/tools/*/ # nuget v3 layout diff --git a/nuget/runners/nunit.console.nuget.agent.addins b/nuget/runners/nunit.console.nuget.agent.addins deleted file mode 100644 index ddfcb54ab..000000000 --- a/nuget/runners/nunit.console.nuget.agent.addins +++ /dev/null @@ -1,11 +0,0 @@ -# Extensions built for a single runtime target -../../../../NUnit.Extension.*/**/tools/ # nuget v2 layout -../../../../../NUnit.Extension.*/**/tools/ # nuget v3 layout -../../../../nunit.extension.*/**/tools/ # nuget v2 layout -../../../../../nunit.extension.*/**/tools/ # nuget v3 layout - -# Extensions built for multiple targets -../../../../NUnit.Extension.*/**/tools/*/ # nuget v2 layout -../../../../../NUnit.Extension.*/**/tools/*/ # nuget v3 layout -../../../../nunit.extension.*/**/tools/*/ # nuget v2 layout -../../../../../nunit.extension.*/**/tools/*/ # nuget v3 layout diff --git a/package-tests.cake b/package-tests.cake index 7c893672e..eab3b20c9 100644 --- a/package-tests.cake +++ b/package-tests.cake @@ -210,7 +210,7 @@ StandardRunnerTests.Add(new PackageTest( KnownExtensions.NUnitProjectLoader)); // V2 Result Writer Test -StandardRunnerTests.Add(new PackageTest( +AddToBothLists(new PackageTest( 1, "V2ResultWriterTest", "Run mock-assembly under .NET 6.0 and produce V2 output", "testdata/net6.0/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2", diff --git a/src/NUnitEngine/nunit.engine.core.tests/Services/ExtensionManagerTests.cs b/src/NUnitEngine/nunit.engine.core.tests/Services/ExtensionManagerTests.cs index eca71b122..dc3e8e12d 100644 --- a/src/NUnitEngine/nunit.engine.core.tests/Services/ExtensionManagerTests.cs +++ b/src/NUnitEngine/nunit.engine.core.tests/Services/ExtensionManagerTests.cs @@ -12,7 +12,7 @@ using NUnit.Engine.Internal.FileSystemAccess; using System.Diagnostics; -namespace NUnit.Engine.Services.Tests +namespace NUnit.Engine.Services { public class ExtensionManagerTests { @@ -58,7 +58,7 @@ public void CreateExtensionManager() // Find actual extension points. _extensionManager.FindExtensionPoints(typeof(CoreEngine).Assembly); _extensionManager.FindExtensionPoints(typeof(ITestEngine).Assembly); - // Find extensions. + // Find extensions directly in the their assemblies #if NETCOREAPP _extensionManager.FindExtensionsInAssembly(FakeExtensions("netstandard2.0")); #else diff --git a/src/NUnitEngine/nunit.engine.core/Services/ExtensionManager.cs b/src/NUnitEngine/nunit.engine.core/Services/ExtensionManager.cs index 8e9d6d449..731ec1ab7 100644 --- a/src/NUnitEngine/nunit.engine.core/Services/ExtensionManager.cs +++ b/src/NUnitEngine/nunit.engine.core/Services/ExtensionManager.cs @@ -15,8 +15,9 @@ namespace NUnit.Engine.Services { public class ExtensionManager : IExtensionManager { - static readonly Logger log = InternalTrace.GetLogger(typeof(ExtensionService)); - static readonly Version ENGINE_VERSION = typeof(ExtensionService).Assembly.GetName().Version; + static readonly Logger log = InternalTrace.GetLogger(typeof(ExtensionManager)); + static readonly Assembly THIS_ASSEMBLY = Assembly.GetExecutingAssembly(); + static readonly Version ENGINE_VERSION = THIS_ASSEMBLY.GetName().Version; private readonly IFileSystem _fileSystem; //private readonly IAddinsFileReader _addinsReader; @@ -120,6 +121,11 @@ public virtual void FindExtensionPoints(params Assembly[] targetAssemblies) } } + /// + /// Find and install extensions starting from a given base directory, + /// and using the contained '.addins' files to direct the search. + /// + /// public void FindExtensions(string startDir) { // Create the list of possible extension assemblies, @@ -131,6 +137,21 @@ public void FindExtensions(string startDir) FindExtensionsInAssembly(candidate); } + /// + /// Find and install extensions starting from a given base directory, + /// and using the provided list of patterns to direct the search using + /// a built-in algorithm. + /// + /// Path to the initial directory. + /// A list of patterns used to identify potential candidates. + public void FindExtensions(string startDir, string[] patterns) + { + FindExtensionAssemblies(_fileSystem.GetDirectory(startDir), patterns); + + foreach (var candidate in _assemblies) + FindExtensionsInAssembly(candidate); + } + /// /// Get an ExtensionPoint based on its unique identifying path. /// @@ -233,14 +254,36 @@ private ExtensionPoint DeduceExtensionPointFromType(TypeReference typeRef) } /// - /// Find candidate extension assemblies starting from a - /// given base directory. + /// Find candidate extension assemblies starting from a given base directory + /// and using the contained '.addins' files to direct the search. /// - /// - private void FindExtensionAssemblies(IDirectory startDir) + /// Path to the initial directory. + private void FindExtensionAssemblies(IDirectory initialDirectory) + { + // Since no patterns are provided, look for addins files + ProcessAddinsFiles(initialDirectory, false); + } + + /// + /// Find candidate extension assemblies starting from a given base directory + /// and using the provided list of patterns to direct the search using + /// a built-in algorithm. + /// + /// Path to the initial directory. + /// A list of patterns used to identify potential candidates. + private void FindExtensionAssemblies(IDirectory initialDirectory, string[] patterns) { - // First check the directory itself - ProcessAddinsFiles(startDir, false); + // Start looking two levels above initial directory + var startDir = initialDirectory.Parent.Parent; + + while (startDir != null) + { + foreach (var pattern in patterns) + foreach (var dir in _directoryFinder.GetDirectories(startDir, pattern)) + ProcessDirectory(dir, true); + + startDir = startDir.Parent; + } } /// diff --git a/src/NUnitEngine/nunit.engine.core/Services/ExtensionService.cs b/src/NUnitEngine/nunit.engine.core/Services/ExtensionService.cs index 74ef1abcf..d3dba41b4 100644 --- a/src/NUnitEngine/nunit.engine.core/Services/ExtensionService.cs +++ b/src/NUnitEngine/nunit.engine.core/Services/ExtensionService.cs @@ -8,6 +8,7 @@ using NUnit.Engine.Internal; using NUnit.Engine.Internal.FileSystemAccess; using NUnit.Engine.Internal.FileSystemAccess.Default; +using System.IO; namespace NUnit.Engine.Services { @@ -18,6 +19,13 @@ namespace NUnit.Engine.Services /// public class ExtensionService : Service, IExtensionService { + private static readonly Assembly THIS_ASSEMBLY = typeof(ExtensionService).Assembly; + + private static readonly string[] CHOCO_PATTERNS = new[] { + "nunit-extension-*/**/tools/", "nunit-extension-*/**/tools/*/" }; + private static readonly string[] NUGET_PATTERNS = new[] { + "NUnit.Extension.*/**/tools/", "NUnit.Extension.*/**/tools/*/" }; + private readonly IExtensionManager _extensionManager; public ExtensionService() @@ -81,8 +89,10 @@ public override void StartService() Assembly.GetExecutingAssembly(), typeof(ITestEngine).Assembly); - var thisAssembly = Assembly.GetExecutingAssembly(); - _extensionManager.FindExtensions(AssemblyHelper.GetDirectoryName(thisAssembly)); + var initialDirectory = AssemblyHelper.GetDirectoryName(THIS_ASSEMBLY); + bool isChocolateyPackage = System.IO.File.Exists(Path.Combine(THIS_ASSEMBLY.Location, "VERIFICATION.txt")); + + _extensionManager.FindExtensions(initialDirectory, isChocolateyPackage ? CHOCO_PATTERNS : NUGET_PATTERNS); Status = ServiceStatus.Started; } diff --git a/src/NUnitEngine/nunit.engine.core/Services/IExtensionManager.cs b/src/NUnitEngine/nunit.engine.core/Services/IExtensionManager.cs index c02704d5a..d688eb328 100644 --- a/src/NUnitEngine/nunit.engine.core/Services/IExtensionManager.cs +++ b/src/NUnitEngine/nunit.engine.core/Services/IExtensionManager.cs @@ -14,7 +14,22 @@ public interface IExtensionManager : IDisposable IEnumerable Extensions { get; } void FindExtensionPoints(params Assembly[] targetAssemblies); - void FindExtensions(string startDir); + + /// + /// Find and install extensions starting from a given base directory, + /// and using the contained '.addins' files to direct the search. + /// + /// Path to the initial directory. + void FindExtensions(string initialDirectory); + + /// + /// Find and install extensions starting from a given base directory, + /// and using the provided list of patterns to direct the search using + /// a built-in algorithm. + /// + /// Path to the initial directory. + /// A list of patterns used to identify potential candidates. + void FindExtensions(string initialDirectory, string[] patterns); IExtensionPoint GetExtensionPoint(string path);