Skip to content

Commit

Permalink
Merge pull request #64 from max-ieremenko/powershell/dependency-loader
Browse files Browse the repository at this point in the history
load internal dependencies into private context
  • Loading branch information
max-ieremenko authored Nov 4, 2024
2 parents 412c777 + 4fb97fb commit d24ba6e
Show file tree
Hide file tree
Showing 26 changed files with 372 additions and 158 deletions.
89 changes: 89 additions & 0 deletions Sources/SqlDatabase.PowerShell.Internal/CmdLetExecutor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using SqlDatabase.Adapter;
using SqlDatabase.CommandLine;
using SqlDatabase.Configuration;

namespace SqlDatabase.PowerShell.Internal;

public static class CmdLetExecutor
{
// only for tests
internal static ISqlDatabaseProgram? Program { get; set; }

public static void RunCreate(IDictionary<string, object?> param, string currentDirectory, Action<string> writeInfo, Action<string> writeError)
{
var commandLine = new CreateCommandLine
{
Database = (string)param[nameof(CreateCommandLine.Database)]!,
Configuration = (string?)param[nameof(CreateCommandLine.Configuration)],
Log = (string?)param[nameof(CreateCommandLine.Log)],
WhatIf = (bool)param[nameof(CreateCommandLine.WhatIf)]!
};

CommandLineTools.AppendFrom(commandLine.From, false, (string[]?)param[nameof(CreateCommandLine.From)]);
CommandLineTools.AppendVariables(commandLine.Variables, (string[]?)param[nameof(CreateCommandLine.Variables)]);

Run(commandLine, currentDirectory, writeInfo, writeError);
}

public static void RunExecute(IDictionary<string, object?> param, string currentDirectory, Action<string> writeInfo, Action<string> writeError)
{
var commandLine = new ExecuteCommandLine
{
Database = (string)param[nameof(ExecuteCommandLine.Database)]!,
Transaction = (TransactionMode)((int)param[nameof(ExecuteCommandLine.Transaction)]!),
Configuration = (string?)param[nameof(ExecuteCommandLine.Configuration)],
Log = (string?)param[nameof(ExecuteCommandLine.Log)],
WhatIf = (bool)param[nameof(ExecuteCommandLine.WhatIf)]!
};

CommandLineTools.AppendFrom(commandLine.From, false, (string[]?)param[nameof(ExecuteCommandLine.From)]);
CommandLineTools.AppendFrom(commandLine.From, true, (string[]?)param["FromSql"]);
CommandLineTools.AppendVariables(commandLine.Variables, (string[]?)param[nameof(ExecuteCommandLine.Variables)]);

Run(commandLine, currentDirectory, writeInfo, writeError);
}

public static void RunExport(IDictionary<string, object?> param, string currentDirectory, Action<string> writeInfo, Action<string> writeError)
{
var commandLine = new ExportCommandLine
{
Database = (string)param[nameof(ExportCommandLine.Database)]!,
Configuration = (string?)param[nameof(ExportCommandLine.Configuration)],
DestinationFileName = (string?)param[nameof(ExportCommandLine.DestinationFileName)],
DestinationTableName = (string?)param[nameof(ExportCommandLine.DestinationTableName)],
Log = (string?)param[nameof(ExecuteCommandLine.Log)]
};

CommandLineTools.AppendFrom(commandLine.From, false, (string[]?)param[nameof(ExportCommandLine.From)]);
CommandLineTools.AppendFrom(commandLine.From, true, (string[]?)param["FromSql"]);
CommandLineTools.AppendVariables(commandLine.Variables, (string[]?)param[nameof(ExportCommandLine.Variables)]);

Run(commandLine, currentDirectory, writeInfo, writeError);
}

public static void RunUpdate(IDictionary<string, object?> param, string currentDirectory, Action<string> writeInfo, Action<string> writeError)
{
var commandLine = new UpgradeCommandLine
{
Database = (string)param[nameof(UpgradeCommandLine.Database)]!,
Transaction = (TransactionMode)((int)param[nameof(UpgradeCommandLine.Transaction)]!),
Configuration = (string?)param[nameof(UpgradeCommandLine.Configuration)],
Log = (string?)param[nameof(UpgradeCommandLine.Log)],
WhatIf = (bool)param[nameof(UpgradeCommandLine.WhatIf)]!,
FolderAsModuleName = (bool)param[nameof(UpgradeCommandLine.FolderAsModuleName)]!
};

CommandLineTools.AppendFrom(commandLine.From, false, (string[]?)param[nameof(UpgradeCommandLine.From)]);
CommandLineTools.AppendVariables(commandLine.Variables, (string[]?)param[nameof(UpgradeCommandLine.Variables)]);

Run(commandLine, currentDirectory, writeInfo, writeError);
}

public static string GetDefaultConfigurationFile() => ConfigurationManager.GetDefaultConfigurationFile();

private static void Run(ICommandLine commandLine, string currentDirectory, Action<string> writeInfo, Action<string> writeError)
{
var program = Program ?? new SqlDatabaseProgram(new CmdLetLogger(writeInfo, writeError), currentDirectory);
program.ExecuteCommand(commandLine);
}
}
19 changes: 19 additions & 0 deletions Sources/SqlDatabase.PowerShell.Internal/CmdLetLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using SqlDatabase.Log;

namespace SqlDatabase.PowerShell.Internal;

internal sealed class CmdLetLogger : LoggerBase
{
private readonly Action<string> _writeInfo;
private readonly Action<string> _writeError;

public CmdLetLogger(Action<string> writeInfo, Action<string> writeError)
{
_writeInfo = writeInfo;
_writeError = writeError;
}

protected override void WriteError(string message) => _writeError(message);

protected override void WriteInfo(string message) => _writeInfo(message);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("SqlDatabase.PowerShell.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010055AB0DC1F8A24FB41E7358B65A606EC92141F1ABAFBFF062635AB5FAEB22308CFFBC8B54F3436694F14F6FD6C145D4F16C13A3E739FFCA837902BB78E2D51B890D964CC7384C2CC6B844AE37323F501F29E3EDC2DFADA82C99F5FBB5197ED757D795C2E5408DCB3FBAF9DDDF39E60B137ED0A23603A361EA811E6ADB605DFECC")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<OutputPath>..\..\bin\SqlDatabase.PowerShell</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\SqlDatabase\SqlDatabase.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,5 @@ public SqlDatabaseProgram(ILogger logger, string currentDirectory)
_currentDirectory = currentDirectory;
}

public void ExecuteCommand(ICommandLine command)
{
Program.RunPowershell(_logger, command, _currentDirectory);
}
public void ExecuteCommand(ICommandLine command) => Program.RunPowershell(_logger, command, _currentDirectory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ namespace SqlDatabase.PowerShell.Internal;
public class DependencyResolverFactoryTest
{
[Test]
[TestCase("Desktop", typeof(PowerShellDesktopDependencyResolver))]
[TestCase(null, typeof(PowerShellDesktopDependencyResolver))]
[TestCase("Core", typeof(PowerShellCoreDependencyResolver))]
public void CreateProgram(string? psEdition, Type expected)
[TestCase("Desktop")]
[TestCase(null)]
public void CreateDesktop(string? psEdition)
{
var psVersionTable = new Hashtable();
if (psEdition != null)
Expand All @@ -21,6 +20,19 @@ public void CreateProgram(string? psEdition, Type expected)

var actual = DependencyResolverFactory.Create(new PSVersionTable(psVersionTable));

actual.ShouldBeOfType(expected);
actual.ShouldBeOfType<PowerShellDesktopDependencyResolver>();
}

[Test]
public void CreateCore()
{
var psVersionTable = new Hashtable
{
{ "PSEdition", "Core" }
};

var ex = Should.Throw<FileNotFoundException>(() => DependencyResolverFactory.Create(new PSVersionTable(psVersionTable)));

ex.Message.ShouldContain("System.Runtime.Loader");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ public void BeforeEachTest()
.Callback<ICommandLine>(_commandLines.Add);

_commandLines.Clear();
PowerShellCommand.Program = program.Object;
CmdLetExecutor.Program = program.Object;
}

[TearDown]
public void AfterEachTest()
{
PowerShellCommand.Program = null;
CmdLetExecutor.Program = null;

foreach (var row in _powerShell.Streams.Information)
{
Expand Down
18 changes: 8 additions & 10 deletions Sources/SqlDatabase.PowerShell/CreateCmdLet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,15 @@ public sealed class CreateCmdLet : PSCmdlet

protected override void ProcessRecord()
{
var commandLine = new CreateCommandLine
var param = new Dictionary<string, object?>
{
Database = Database,
Configuration = Configuration,
Log = Log,
WhatIf = WhatIf
{ nameof(CreateCommandLine.Database), Database },
{ nameof(CreateCommandLine.Configuration), Configuration },
{ nameof(CreateCommandLine.Log), Log },
{ nameof(CreateCommandLine.WhatIf), (bool)WhatIf },
{ nameof(CreateCommandLine.From), From },
{ nameof(CreateCommandLine.Variables), Var }
};

CommandLineTools.AppendFrom(commandLine.From, false, From);
CommandLineTools.AppendVariables(commandLine.Variables, Var);

PowerShellCommand.Execute(this, commandLine);
PowerShellCommand.Execute(this, nameof(CmdLetExecutor.RunCreate), param);
}
}
23 changes: 10 additions & 13 deletions Sources/SqlDatabase.PowerShell/ExecuteCmdLet.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Management.Automation;
using SqlDatabase.Adapter;
using SqlDatabase.CommandLine;
using SqlDatabase.PowerShell.Internal;

Expand Down Expand Up @@ -41,19 +40,17 @@ public sealed class ExecuteCmdLet : PSCmdlet

protected override void ProcessRecord()
{
var commandLine = new ExecuteCommandLine
var param = new Dictionary<string, object?>
{
Database = Database,
Transaction = (TransactionMode)Transaction,
Configuration = Configuration,
Log = Log,
WhatIf = WhatIf
{ nameof(ExecuteCommandLine.Database), Database },
{ nameof(ExecuteCommandLine.Transaction), (int)Transaction },
{ nameof(ExecuteCommandLine.Configuration), Configuration },
{ nameof(ExecuteCommandLine.Log), Log },
{ nameof(ExecuteCommandLine.WhatIf), (bool)WhatIf },
{ nameof(ExecuteCommandLine.From), From },
{ "FromSql", FromSql },
{ nameof(ExecuteCommandLine.Variables), Var }
};

CommandLineTools.AppendFrom(commandLine.From, false, From);
CommandLineTools.AppendFrom(commandLine.From, true, FromSql);
CommandLineTools.AppendVariables(commandLine.Variables, Var);

PowerShellCommand.Execute(this, commandLine);
PowerShellCommand.Execute(this, nameof(CmdLetExecutor.RunExecute), param);
}
}
22 changes: 10 additions & 12 deletions Sources/SqlDatabase.PowerShell/ExportCmdLet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,17 @@ public sealed class ExportCmdLet : PSCmdlet

protected override void ProcessRecord()
{
var commandLine = new ExportCommandLine
var param = new Dictionary<string, object?>
{
Database = Database,
Configuration = Configuration,
DestinationFileName = ToFile,
DestinationTableName = ToTable,
Log = Log
{ nameof(ExportCommandLine.Database), Database },
{ nameof(ExportCommandLine.Configuration), Configuration },
{ nameof(ExportCommandLine.DestinationFileName), ToFile },
{ nameof(ExportCommandLine.DestinationTableName), ToTable },
{ nameof(ExportCommandLine.Log), Log },
{ nameof(ExportCommandLine.From), From },
{ "FromSql", FromSql },
{ nameof(ExportCommandLine.Variables), Var }
};

CommandLineTools.AppendFrom(commandLine.From, false, From);
CommandLineTools.AppendFrom(commandLine.From, true, FromSql);
CommandLineTools.AppendVariables(commandLine.Variables, Var);

PowerShellCommand.Execute(this, commandLine);
PowerShellCommand.Execute(this, nameof(CmdLetExecutor.RunExport), param);
}
}
14 changes: 2 additions & 12 deletions Sources/SqlDatabase.PowerShell/InfoCmdLet.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Management.Automation;
using System.Runtime.InteropServices;
using SqlDatabase.Configuration;
using SqlDatabase.PowerShell.Internal;

namespace SqlDatabase.PowerShell;
Expand All @@ -9,15 +8,6 @@ namespace SqlDatabase.PowerShell;
public sealed class InfoCmdLet : PSCmdlet
{
protected override void ProcessRecord()
{
using (var resolver = DependencyResolverFactory.Create(this))
{
resolver.Initialize();
WriteInfo();
}
}

private void WriteInfo()
{
var assembly = GetType().Assembly;

Expand All @@ -33,9 +23,9 @@ private void WriteInfo()
RuntimeInformation.OSDescription,
RuntimeInformation.OSArchitecture,
RuntimeInformation.ProcessArchitecture,
Location = Path.GetDirectoryName(assembly.Location),
Location = assembly.GetDirectoryLocation(),
WorkingDirectory = this.GetWorkingDirectory(),
DefaultConfigurationFile = ConfigurationManager.GetDefaultConfigurationFile()
DefaultConfigurationFile = PowerShellCommand.GetDefaultConfigurationFile(this)
});
}
}
26 changes: 3 additions & 23 deletions Sources/SqlDatabase.PowerShell/Internal/AssemblyCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,19 @@

namespace SqlDatabase.PowerShell.Internal;

internal sealed class AssemblyCache : IDisposable
internal sealed class AssemblyCache
{
private readonly string[] _probingPaths;
private readonly IDictionary<string, Assembly?> _assemblyByName;

public AssemblyCache(params string[] probingPaths)
{
_probingPaths = new string[probingPaths.Length + 1];
_probingPaths[0] = Path.GetDirectoryName(GetType().Assembly.Location);
for (var i = 0; i < probingPaths.Length; i++)
{
_probingPaths[i + 1] = probingPaths[i];
}

_assemblyByName = new Dictionary<string, Assembly?>(StringComparer.OrdinalIgnoreCase);
_probingPaths = probingPaths;
}

public Assembly? Load(AssemblyName assemblyName, Func<string, Assembly> loader)
{
var fileName = assemblyName.Name + ".dll";
if (_assemblyByName.TryGetValue(fileName, out var assembly))
{
return assembly;
}

assembly = TryFindAndLoad(fileName, loader);
_assemblyByName[fileName] = assembly;
return assembly;
}

public void Dispose()
{
_assemblyByName.Clear();
return TryFindAndLoad(fileName, loader);
}

private Assembly? TryFindAndLoad(string fileName, Func<string, Assembly> loader)
Expand Down
Loading

0 comments on commit d24ba6e

Please sign in to comment.