diff --git a/.gitignore b/.gitignore index 02ddbb2..1423320 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,11 @@ _ReSharper.* *.swp *.resharper.user *.rptproj.user -*.db \ No newline at end of file +*.db +/.vs +/packages +/Humpback.Tests/.vs +/Humpback.Smo/.vs +/Humpback/.vs +/MigrationBackup +/Humpback.Interfaces/.vs diff --git a/Humpback.Interfaces/Humpback.Interfaces.csproj b/Humpback.Interfaces/Humpback.Interfaces.csproj index a52fc7d..68f2a58 100644 --- a/Humpback.Interfaces/Humpback.Interfaces.csproj +++ b/Humpback.Interfaces/Humpback.Interfaces.csproj @@ -1,17 +1,17 @@  - + + Debug AnyCPU - 8.0.30703 - 2.0 - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1} + {15EADEC7-BE27-4334-BA95-0FF3F6BD8A78} Library Properties Humpback.Interfaces Humpback.Interfaces - v4.0 + v4.7.2 512 + true true @@ -37,9 +37,13 @@ + + + Properties\SharedVersionInfo.cs + @@ -47,11 +51,4 @@ - \ No newline at end of file diff --git a/Humpback.Interfaces/IDatabaseProvider.cs b/Humpback.Interfaces/IDatabaseProvider.cs index 753c889..7d2d569 100644 --- a/Humpback.Interfaces/IDatabaseProvider.cs +++ b/Humpback.Interfaces/IDatabaseProvider.cs @@ -1,5 +1,7 @@ -namespace Humpback.Interfaces { - public interface IDatabaseProvider { +namespace Humpback.Interfaces +{ + public interface IDatabaseProvider + { int GetMigrationVersion(); void UpdateMigrationVersion(int number); diff --git a/Humpback.Interfaces/IFileWriter.cs b/Humpback.Interfaces/IFileWriter.cs index 4e5b8e7..709c3be 100644 --- a/Humpback.Interfaces/IFileWriter.cs +++ b/Humpback.Interfaces/IFileWriter.cs @@ -1,5 +1,7 @@ -namespace Humpback.Interfaces { - public interface IFileWriter { +namespace Humpback.Interfaces +{ + public interface IFileWriter + { void WriteFile(string path, string contents); bool FileExists(string path); } diff --git a/Humpback.Interfaces/IMigrationProvider.cs b/Humpback.Interfaces/IMigrationProvider.cs index 65ce070..6fde058 100644 --- a/Humpback.Interfaces/IMigrationProvider.cs +++ b/Humpback.Interfaces/IMigrationProvider.cs @@ -1,7 +1,9 @@ using System.Collections.Generic; -namespace Humpback.Interfaces { - public interface IMigrationProvider { +namespace Humpback.Interfaces +{ + public interface IMigrationProvider + { SortedDictionary GetMigrations(); SortedDictionary GetMigrationsContents(); KeyValuePair GetMigrationWithContents(int migration_number); diff --git a/Humpback.Interfaces/ISqlFormatter.cs b/Humpback.Interfaces/ISqlFormatter.cs index fb4c8b5..7c84b93 100644 --- a/Humpback.Interfaces/ISqlFormatter.cs +++ b/Humpback.Interfaces/ISqlFormatter.cs @@ -1,5 +1,7 @@ -namespace Humpback.Interfaces { - public interface ISqlFormatter { +namespace Humpback.Interfaces +{ + public interface ISqlFormatter + { string[] GenerateSQLUp(dynamic operation); string[] GenerateSQLDown(dynamic operation); string sql_file_name(string p); diff --git a/Humpback.Interfaces/Properties/AssemblyInfo.cs b/Humpback.Interfaces/Properties/AssemblyInfo.cs index caa13a7..72aac81 100644 --- a/Humpback.Interfaces/Properties/AssemblyInfo.cs +++ b/Humpback.Interfaces/Properties/AssemblyInfo.cs @@ -1,8 +1,7 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Humpback.Interfaces")] @@ -14,23 +13,10 @@ [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("11266294-df7c-4416-8aae-9f9290fc8382")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.2.0.0")] -[assembly: AssemblyFileVersion("0.2.0.0")] +[assembly: Guid("15eadec7-be27-4334-ba95-0ff3f6bd8a78")] diff --git a/Humpback.Smo/Executor.cs b/Humpback.Smo/Executor.cs index ee12d4c..18854ab 100644 --- a/Humpback.Smo/Executor.cs +++ b/Humpback.Smo/Executor.cs @@ -1,20 +1,21 @@ -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Smo; -namespace Humpback.Smo { - public static class Executor { - - public static int Execute(string connection_string, string sql) { - using (var conn = new SqlConnection(connection_string)) { - var server = new Server(new ServerConnection(conn)); - conn.Open(); - return server.ConnectionContext.ExecuteNonQuery(sql); - } +namespace Humpback.Smo +{ + public static class Executor + { + /// + /// Execute TSQL strings using Microsoft.SqlServer.Management.Smo. + /// + /// Config connection string. + /// Compiled TSQL script. + /// number of records affected. + public static int Execute(string connection_string, string sql) + { + var connection = new Microsoft.Data.SqlClient.SqlConnection(connection_string); + Server server = new Server(new ServerConnection(connection)); + return server.ConnectionContext.ExecuteNonQuery(sql); } } } diff --git a/Humpback.Smo/Humpback.Smo.csproj b/Humpback.Smo/Humpback.Smo.csproj index 0cb774b..5b53ea7 100644 --- a/Humpback.Smo/Humpback.Smo.csproj +++ b/Humpback.Smo/Humpback.Smo.csproj @@ -1,17 +1,19 @@  - + + Debug AnyCPU - 8.0.30703 - 2.0 - {347115FF-034F-4257-B873-88C4B6D42FDC} + {804678AE-B193-4A4E-ADE7-B02B66361F73} Library Properties Humpback.Smo Humpback.Smo - v4.0 + v4.7.2 512 + true + + true @@ -31,32 +33,270 @@ 4 - - - - True + + ..\packages\Azure.Core.1.44.1\lib\net472\Azure.Core.dll + + + ..\packages\Azure.Identity.1.13.1\lib\netstandard2.0\Azure.Identity.dll + + + ..\packages\Microsoft.Bcl.AsyncInterfaces.9.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Bcl.TimeProvider.9.0.0\lib\net462\Microsoft.Bcl.TimeProvider.dll + + + ..\packages\Microsoft.Data.SqlClient.5.2.2\lib\net462\Microsoft.Data.SqlClient.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.Data.Tools.Sql.BatchParser.dll + + + ..\packages\Microsoft.Identity.Client.4.66.2\lib\net472\Microsoft.Identity.Client.dll + + + ..\packages\Microsoft.Identity.Client.Extensions.Msal.4.66.2\lib\netstandard2.0\Microsoft.Identity.Client.Extensions.Msal.dll + + + ..\packages\Microsoft.IdentityModel.Abstractions.8.2.1\lib\net472\Microsoft.IdentityModel.Abstractions.dll + + + ..\packages\Microsoft.IdentityModel.JsonWebTokens.8.2.1\lib\net472\Microsoft.IdentityModel.JsonWebTokens.dll + + + ..\packages\Microsoft.IdentityModel.Logging.8.2.1\lib\net472\Microsoft.IdentityModel.Logging.dll + + + ..\packages\Microsoft.IdentityModel.Protocols.8.2.1\lib\net472\Microsoft.IdentityModel.Protocols.dll + + + ..\packages\Microsoft.IdentityModel.Protocols.OpenIdConnect.8.2.1\lib\net472\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll + + + ..\packages\Microsoft.IdentityModel.Tokens.8.2.1\lib\net472\Microsoft.IdentityModel.Tokens.dll + + + ..\packages\Microsoft.SqlServer.Assessment.1.1.17\lib\net462\Microsoft.SqlServer.Assessment.dll + + + ..\packages\Microsoft.SqlServer.Assessment.Authoring.1.1.0\lib\net462\Microsoft.SqlServer.Assessment.Types.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.ConnectionInfo.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Dmf.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Dmf.Common.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.Assessment.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.Collector.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.CollectorEnum.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.HadrData.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.HadrModel.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.RegisteredServers.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.Sdk.Sfc.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.SqlScriptPublish.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.XEvent.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.XEventDbScoped.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.XEventDbScopedEnum.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Management.XEventEnum.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.PolicyEnum.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.RegSvrEnum.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.ServiceBrokerEnum.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Smo.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.Smo.Notebook.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.SmoExtended.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.SqlClrProvider.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.SqlEnum.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.SqlWmiManagement.dll + + + ..\packages\Microsoft.SqlServer.SqlManagementObjects.172.52.0\lib\net472\Microsoft.SqlServer.WmiEnum.dll + + + ..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll + + ..\packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll + + + ..\packages\System.ClientModel.1.2.1\lib\netstandard2.0\System.ClientModel.dll + + + + + ..\packages\System.Configuration.ConfigurationManager.9.0.0\lib\net462\System.Configuration.ConfigurationManager.dll + + + + ..\packages\System.Diagnostics.DiagnosticSource.9.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll + + + + + + ..\packages\System.IdentityModel.Tokens.Jwt.8.2.1\lib\net472\System.IdentityModel.Tokens.Jwt.dll + + + ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll + True + True + + + ..\packages\System.IO.FileSystem.AccessControl.5.0.0\lib\net461\System.IO.FileSystem.AccessControl.dll + + + ..\packages\System.IO.Pipelines.9.0.0\lib\net462\System.IO.Pipelines.dll + + + ..\packages\System.Memory.4.6.0\lib\net462\System.Memory.dll + + + ..\packages\System.Memory.Data.9.0.0\lib\net462\System.Memory.Data.dll + + + + ..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll + True + True + + + + ..\packages\System.Numerics.Vectors.4.6.0\lib\net462\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll + True + True + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.1.0\lib\net462\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + + + + ..\packages\System.Security.AccessControl.6.0.1\lib\net461\System.Security.AccessControl.dll + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll + True + True + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + ..\packages\System.Security.Cryptography.ProtectedData.9.0.0\lib\net462\System.Security.Cryptography.ProtectedData.dll + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + + + ..\packages\System.Security.Permissions.9.0.0\lib\net462\System.Security.Permissions.dll + + + ..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + + + + ..\packages\System.Text.Encodings.Web.9.0.0\lib\net462\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.9.0.0\lib\net462\System.Text.Json.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.6.0\lib\net462\System.Threading.Tasks.Extensions.dll + + + + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + + + + + Properties\SharedVersionInfo.cs + + + + + + + + - - xcopy $(TargetPath) $(SolutionDir)Humpback\Artifacts /Y - - \ No newline at end of file diff --git a/Humpback.Smo/ILLink/ILLink.Descriptors.LibraryBuild.xml b/Humpback.Smo/ILLink/ILLink.Descriptors.LibraryBuild.xml new file mode 100644 index 0000000..a42d7f0 --- /dev/null +++ b/Humpback.Smo/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Humpback.Smo/Properties/AssemblyInfo.cs b/Humpback.Smo/Properties/AssemblyInfo.cs index 992a991..2142a86 100644 --- a/Humpback.Smo/Properties/AssemblyInfo.cs +++ b/Humpback.Smo/Properties/AssemblyInfo.cs @@ -1,8 +1,7 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Humpback.Smo")] @@ -14,23 +13,10 @@ [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("9265f0fb-a77c-4dd8-b1ec-c3ee8834c3fa")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.2.0.0")] -[assembly: AssemblyFileVersion("0.2.0.0")] +[assembly: Guid("804678ae-b193-4a4e-ade7-b02b66361f73")] diff --git a/Humpback.Smo/app.config b/Humpback.Smo/app.config new file mode 100644 index 0000000..fc98ecb --- /dev/null +++ b/Humpback.Smo/app.config @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Humpback.Smo/packages.config b/Humpback.Smo/packages.config new file mode 100644 index 0000000..6a183f2 --- /dev/null +++ b/Humpback.Smo/packages.config @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Humpback.Tests/ConfigurationTest.cs b/Humpback.Tests/ConfigurationTest.cs index a751386..25d99c8 100644 --- a/Humpback.Tests/ConfigurationTest.cs +++ b/Humpback.Tests/ConfigurationTest.cs @@ -1,22 +1,24 @@ -using System.Linq; -using Humpback.ConfigurationOptions; +using Humpback.ConfigurationOptions; using System; +using System.Linq; using Xunit; namespace Humpback.Tests { - - public class ConfigurationTest { + + public class ConfigurationTest + { /// ///A test for Configuration Constructor /// [Fact] - public void ConfigurationConstructorTestNullConstructorParam() { + public void ConfigurationConstructorTestNullConstructorParam() + { string[] options = null; // TODO: Initialize to an appropriate value Configuration target = new Configuration(options); Assert.True(target.WriteHelp); - Assert.Equal(0,target.MigrateToVersion); + Assert.Equal(0, target.MigrateToVersion); } @@ -24,7 +26,8 @@ public void ConfigurationConstructorTestNullConstructorParam() { ///A test for Configuration Constructor /// [Fact] - public void ConfigurationConstructorTestDefaultConstructor() { + public void ConfigurationConstructorTestDefaultConstructor() + { Configuration target = new Configuration(); Assert.True(target.WriteHelp); Assert.Equal(0, target.MigrateToVersion); @@ -35,27 +38,32 @@ public void ConfigurationConstructorTestDefaultConstructor() { ///A test for Help /// [Fact] - public void HelpTestDash() { - var target = new Configuration(new[]{"-?"}); + public void HelpTestDash() + { + var target = new Configuration(new[] { "-?" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpTest_h() { + public void HelpTest_h() + { var target = new Configuration(new[] { "-h" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpTest_H() { + public void HelpTest_H() + { var target = new Configuration(new[] { "-H" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpTest_HELP() { + public void HelpTest_HELP() + { var target = new Configuration(new[] { "-HELP" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpTest_help() { + public void HelpTest_help() + { var target = new Configuration(new[] { "-help" }); Assert.True(target.WriteHelp); } @@ -64,48 +72,57 @@ public void HelpTest_help() { ///A test for HelpModifier /// [Fact] - public void HelpModifierTest_Run() { + public void HelpModifierTest_Run() + { var target = new Configuration(new[] { "-?", "Migrate" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpModifierTest_RUN() { + public void HelpModifierTest_RUN() + { var target = new Configuration(new[] { "-?", "MIGRATE" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpModifierTest_List() { + public void HelpModifierTest_List() + { var target = new Configuration(new[] { "-?", "List" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpModifierTest_Generate() { + public void HelpModifierTest_Generate() + { var target = new Configuration(new[] { "-?", "Generate" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpModifierTest_Sql() { + public void HelpModifierTest_Sql() + { var target = new Configuration(new[] { "-?", "Sql" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpModifierTest_R() { + public void HelpModifierTest_R() + { var target = new Configuration(new[] { "-?", "M" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpModifierTest_L() { + public void HelpModifierTest_L() + { var target = new Configuration(new[] { "-?", "L" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpModifierTest_G() { - var target = new Configuration(new[] { "-?","G" }); + public void HelpModifierTest_G() + { + var target = new Configuration(new[] { "-?", "G" }); Assert.True(target.WriteHelp); } [Fact] - public void HelpModifierTest_S_and_Ensure_Run_Off() { + public void HelpModifierTest_S_and_Ensure_Run_Off() + { var target = new Configuration(new[] { "-?", "S" }); Assert.True(target.WriteHelp); Assert.False(target.Migrate); @@ -113,19 +130,22 @@ public void HelpModifierTest_S_and_Ensure_Run_Off() { [Fact] - public void BasicSqlTest() { + public void BasicSqlTest() + { Configuration target = new Configuration(new[] { "-S" }); Assert.True(target.Sql); } [Fact] - public void BasicSqlTest2() { + public void BasicSqlTest2() + { Configuration target = new Configuration(new[] { "--Sql" }); Assert.True(target.Sql); Assert.False(target.WriteHelp); Assert.False(target.Migrate); } [Fact] - public void BasicSqlTest3() { + public void BasicSqlTest3() + { Configuration target = new Configuration(new[] { "/Sql" }); Assert.True(target.Sql); Assert.False(target.WriteHelp); @@ -135,18 +155,23 @@ public void BasicSqlTest3() { } [Fact] - public void BasicGenerateErrorTest() { - try { - Configuration target = new Configuration(new[] {"-G"}); + public void BasicGenerateErrorTest() + { + try + { + Configuration target = new Configuration(new[] { "-G" }); Assert.True(false, "Configuration should have failed"); - } catch (Exception ex) { + } + catch (Exception ex) + { Assert.NotNull(ex); } } [Fact] - public void BasicGenerateTest() { - Configuration target = new Configuration(new[] { "-G","AddMyMigration" }); + public void BasicGenerateTest() + { + Configuration target = new Configuration(new[] { "-G", "AddMyMigration" }); Assert.True(target.Generate); Assert.False(target.WriteHelp); Assert.False(target.Migrate); @@ -154,26 +179,29 @@ public void BasicGenerateTest() { } [Fact] - public void GenerateTest() { + public void GenerateTest() + { Configuration target = new Configuration(new[] { "-G", "table", "first_name:string", "last_name:string" }); Assert.True(target.Generate); Assert.False(target.WriteHelp); Assert.False(target.Migrate); Assert.False(target.List); - Console.WriteLine(String.Join("|",target.Extra.ToArray())); + Console.WriteLine(String.Join("|", target.Extra.ToArray())); Assert.NotNull(target.Extra); Assert.True(target.Extra.Count() > 0); } [Fact] - public void GenerateTest_CreateTable() { + public void GenerateTest_CreateTable() + { Configuration target = new Configuration(new[] { "--G", "users", "first_name:string", "last_name" }); Assert.True(target.Generate); - Assert.Equal("users", target.GenerateString); + Assert.Equal("users", target.GenerateString); } [Fact] - public void GenerateTest_ModifyTable() { + public void GenerateTest_ModifyTable() + { Configuration target = new Configuration(new[] { "--G", "AddAgeToUsers", "first_name:string", "last_name" }); Assert.True(target.Generate); Assert.Equal("AddAgeToUsers", target.GenerateString); @@ -181,7 +209,8 @@ public void GenerateTest_ModifyTable() { [Fact] - public void BasicListTest() { + public void BasicListTest() + { Configuration target = new Configuration(new[] { "-List" }); Assert.True(target.List); Assert.False(target.WriteHelp); @@ -189,7 +218,8 @@ public void BasicListTest() { Assert.False(target.Generate); } [Fact] - public void BasicRunTest() { + public void BasicRunTest() + { Configuration target = new Configuration(new[] { "-m" }); Assert.True(target.Migrate); Assert.False(target.WriteHelp); @@ -199,7 +229,8 @@ public void BasicRunTest() { [Fact] - public void EnvironmentTest() { + public void EnvironmentTest() + { Configuration target = new Configuration(new[] { "-e" }); Assert.True(target.Env); Assert.False(target.WriteHelp); @@ -208,7 +239,8 @@ public void EnvironmentTest() { } [Fact] - public void EnvironmentTestSet() { + public void EnvironmentTestSet() + { Configuration target = new Configuration(new[] { "-e", "-set", "name" }); Assert.True(target.Env); Assert.Equal(target.set_current_settings, "name"); @@ -216,14 +248,16 @@ public void EnvironmentTestSet() { [Fact] - public void EnvironmentTestAdd() { + public void EnvironmentTestAdd() + { Configuration target = new Configuration(new[] { "-e", "-add", "name" }); Assert.True(target.Env); Assert.Equal(target.new_project_name, "name"); } [Fact] - public void EnvironmentTestRemove() { + public void EnvironmentTestRemove() + { Configuration target = new Configuration(new[] { "-e", "-remove", "name" }); Assert.True(target.Env); Assert.Equal(target.remove_project_name, "name"); @@ -231,28 +265,32 @@ public void EnvironmentTestRemove() { [Fact] - public void EnvironmentTestRename() { + public void EnvironmentTestRename() + { Configuration target = new Configuration(new[] { "-e", "-rename", "name" }); Assert.True(target.Env); Assert.Equal(target.settings_rename, "name"); } [Fact] - public void EnvironmentTestDir() { + public void EnvironmentTestDir() + { Configuration target = new Configuration(new[] { "-e", "-dir", "name" }); Assert.True(target.Env); Assert.Equal(target.settings_dir, "name"); } [Fact] - public void EnvironmentTestConnectionString() { + public void EnvironmentTestConnectionString() + { Configuration target = new Configuration(new[] { "-e", "-cs", "name" }); Assert.True(target.Env); Assert.Equal(target.settings_cs, "name"); } [Fact] - public void EnvironmentTestFlavor() { + public void EnvironmentTestFlavor() + { Configuration target = new Configuration(new[] { "-e", "-flavor", "name" }); Assert.True(target.Env); Assert.Equal(target.settings_flavor, "name"); diff --git a/Humpback.Tests/DynamicTests.cs b/Humpback.Tests/DynamicTests.cs index b072c14..84569d2 100644 --- a/Humpback.Tests/DynamicTests.cs +++ b/Humpback.Tests/DynamicTests.cs @@ -1,25 +1,25 @@ using System; -using System.Text; -using System.Collections.Generic; -using System.Linq; -using Humpback.Parts; using Xunit; -namespace Humpback.Tests { - public class DynamicTests { +namespace Humpback.Tests +{ + public class DynamicTests + { [Fact] - public void TestForArray() { + public void TestForArray() + { //dynamic d = new { name = "jason", things = new{val="stuff"} }; // throws error testing for Length property - dynamic e = new { name = "jason", things = new[]{"stuff","morestuff"} }; + dynamic e = new { name = "jason", things = new[] { "stuff", "morestuff" } }; Assert.NotNull(e.things.Length); } [Fact] - public void TestForArrayOnString() { + public void TestForArrayOnString() + { //dynamic d = new { name = "jason", things = new{val="stuff"} }; // throws error testing for Length property dynamic e = new { name = "jason", things = new[] { "stuff", "morestuff" } }; @@ -28,7 +28,8 @@ public void TestForArrayOnString() { } [Fact] - public void TestForString() { + public void TestForString() + { //dynamic d = new { name = "jason", things = new{val="stuff"} }; // throws error testing for Length property dynamic e = new { name = "jason", things = new[] { "stuff", "morestuff" } }; @@ -37,7 +38,8 @@ public void TestForString() { } [Fact] - public void TestForStringOnArray() { + public void TestForStringOnArray() + { //dynamic d = new { name = "jason", things = new{val="stuff"} }; // throws error testing for Length property dynamic e = new { name = "jason", things = new[] { "stuff", "morestuff" } }; @@ -46,7 +48,8 @@ public void TestForStringOnArray() { } [Fact] - public void TestForTypeOfArray() { + public void TestForTypeOfArray() + { //dynamic d = new { name = "jason", things = new{val="stuff"} }; // throws error testing for Length property dynamic e = new { name = new { name2 = "jason" }, things = new[] { new { name2 = "jason" }, new { name2 = "jason" } } }; diff --git a/Humpback.Tests/GeneratorTest.cs b/Humpback.Tests/GeneratorTest.cs index 12a4deb..e90ccc8 100644 --- a/Humpback.Tests/GeneratorTest.cs +++ b/Humpback.Tests/GeneratorTest.cs @@ -1,18 +1,18 @@ -using Humpback.Parts; +using Humpback.ConfigurationOptions; +using Humpback.Parts; using Humpback.Tests.Impl; -using System; -using Humpback.ConfigurationOptions; -using Humpback; -using System.Collections.Generic; using Xunit; namespace Humpback.Tests { - - public class GeneratorTest { - private static Settings Settings { - get { + public class GeneratorTest + { + + private static Settings Settings + { + get + { return TestHelpers.TestSettings; } @@ -21,9 +21,10 @@ private static Settings Settings { ///A test for Generator /// [Fact] - public void GeneratorAddTableNoColumnsSpecified() { - Configuration configuration = new Configuration(new[] { "-g","Users" }); - TestFileWriter file_writer = new TestFileWriter(); + public void GeneratorAddTableNoColumnsSpecified() + { + Configuration configuration = new Configuration(new[] { "-g", "Users" }); + TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); target.Execute(); Assert.True(file_writer.FileName.Contains("Users")); @@ -32,7 +33,8 @@ public void GeneratorAddTableNoColumnsSpecified() { } [Fact] - public void GeneratorAddTable1Column() { + public void GeneratorAddTable1Column() + { Configuration configuration = new Configuration(new[] { "-g", "Users", "first_name:string" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -47,7 +49,8 @@ public void GeneratorAddTable1Column() { } [Fact] - public void GeneratorAddTableMultipleColumn() { + public void GeneratorAddTableMultipleColumn() + { Configuration configuration = new Configuration(new[] { "-g", "Users", "first_name:string", "last_name:string" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -62,7 +65,8 @@ public void GeneratorAddTableMultipleColumn() { Assert.True(file_writer.FileContents.Contains("full_audit")); } [Fact] - public void GeneratorAddTableMultipleColumnWithNullable() { + public void GeneratorAddTableMultipleColumnWithNullable() + { Configuration configuration = new Configuration(new[] { "-g", "Users", "first_name:string:false", "last_name:string:true:'welty'" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -80,7 +84,8 @@ public void GeneratorAddTableMultipleColumnWithNullable() { } [Fact] - public void GeneratorDropTable() { + public void GeneratorDropTable() + { Configuration configuration = new Configuration(new[] { "-g", "DropUsers" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -93,7 +98,8 @@ public void GeneratorDropTable() { } [Fact] - public void GeneratorRemoveColumn() { + public void GeneratorRemoveColumn() + { Configuration configuration = new Configuration(new[] { "-g", "Removefirst_nameFromUsers" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -108,7 +114,8 @@ public void GeneratorRemoveColumn() { ///A test for AddColumn /// [Fact] - public void GeneratorAddSingleColumnTest() { + public void GeneratorAddSingleColumnTest() + { Configuration configuration = new Configuration(new[] { "-g", "addfirst_nametoUsers" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -121,7 +128,8 @@ public void GeneratorAddSingleColumnTest() { } [Fact] - public void GeneratorAddSingleColumnTest_Escaped_To() { + public void GeneratorAddSingleColumnTest_Escaped_To() + { Configuration configuration = new Configuration(new[] { "-g", "addcustomer_name_to_Users" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -134,7 +142,8 @@ public void GeneratorAddSingleColumnTest_Escaped_To() { } [Fact] - public void GeneratorAddSingleColumnTestDuplicateTo() { + public void GeneratorAddSingleColumnTestDuplicateTo() + { Configuration configuration = new Configuration(new[] { "-g", "addcustomernametoUsers" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -143,7 +152,8 @@ public void GeneratorAddSingleColumnTestDuplicateTo() { } [Fact] - public void GeneratorAddMultipleColumnTest() { + public void GeneratorAddMultipleColumnTest() + { Configuration configuration = new Configuration(new[] { "-g", "addfirst_nametoUsers", "first_name:string", "last_name:string" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -158,7 +168,8 @@ public void GeneratorAddMultipleColumnTest() { [Fact] - public void GeneratorAddReferenceColumnTest() { + public void GeneratorAddReferenceColumnTest() + { Configuration configuration = new Configuration(new[] { "-g", "AddUserToOrders", "User:reference" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -176,7 +187,8 @@ public void GeneratorAddReferenceColumnTest() { ///A test for AddColumn /// [Fact] - public void GeneratorChangeSingleColumnTest() { + public void GeneratorChangeSingleColumnTest() + { Configuration configuration = new Configuration(new[] { "-g", "ChangeUsers", "first_name:string" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -189,7 +201,8 @@ public void GeneratorChangeSingleColumnTest() { Assert.True(file_writer.FileContents.Contains("down")); } [Fact] - public void GeneratorChangeMultipleColumnTest() { + public void GeneratorChangeMultipleColumnTest() + { Configuration configuration = new Configuration(new[] { "-g", "ChangeUsers", "first_name:string", "last_name:string" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -206,7 +219,8 @@ public void GeneratorChangeMultipleColumnTest() { ///A test for AddIndex /// [Fact] - public void GeneratorAddIndexTest() { + public void GeneratorAddIndexTest() + { Configuration configuration = new Configuration(new[] { "-g", "addindextoUsers", "first_name", "last_name" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -219,7 +233,8 @@ public void GeneratorAddIndexTest() { Assert.True(file_writer.FileContents.Contains("last_name")); } [Fact] - public void GeneratorDropIndexTest() { + public void GeneratorDropIndexTest() + { Configuration configuration = new Configuration(new[] { "-g", "removeindexfromUsers", "first_name", "last_name" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -236,7 +251,8 @@ public void GeneratorDropIndexTest() { ///A test for File /// [Fact] - public void GeneratorFileTest() { + public void GeneratorFileTest() + { Configuration configuration = new Configuration(new[] { "-g", "File", "mysqlfile" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); @@ -245,7 +261,7 @@ public void GeneratorFileTest() { Assert.True(file_writer.FileContents.Contains("file")); Assert.True(file_writer.FileContents.Contains("mysqlfile")); Assert.True(file_writer.FileContents.Contains("up")); - + } @@ -253,7 +269,8 @@ public void GeneratorFileTest() { ///A test for Raw SQL /// [Fact] - public void GeneratorSqlTest() { + public void GeneratorSqlTest() + { Configuration configuration = new Configuration(new[] { "-g", "SQL", "CREATE TABLE Users (ID {pk}, first_name {string} NOT NULL, price_paid {money})" }); TestFileWriter file_writer = new TestFileWriter(); IHumpbackCommand target = new Generator(configuration, Settings, file_writer); diff --git a/Humpback.Tests/Humpback.Tests.csproj b/Humpback.Tests/Humpback.Tests.csproj index a029050..69fd83d 100644 --- a/Humpback.Tests/Humpback.Tests.csproj +++ b/Humpback.Tests/Humpback.Tests.csproj @@ -1,19 +1,29 @@  - + + + + + + + Debug AnyCPU - - - 2.0 - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680} + {6E00DC4B-EF35-41F3-9553-CE3F867F6AE6} Library Properties Humpback.Tests Humpback.Tests - v4.0 + v4.7.2 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + true @@ -33,28 +43,83 @@ 4 + + ..\packages\Microsoft.ApplicationInsights.2.22.0\lib\net46\Microsoft.ApplicationInsights.dll + + + ..\packages\Microsoft.Testing.Extensions.Telemetry.1.4.3\lib\netstandard2.0\Microsoft.Testing.Extensions.Telemetry.dll + + + ..\packages\Microsoft.Testing.Extensions.TrxReport.Abstractions.1.4.3\lib\netstandard2.0\Microsoft.Testing.Extensions.TrxReport.Abstractions.dll + + + ..\packages\Microsoft.Testing.Extensions.VSTestBridge.1.4.3\lib\netstandard2.0\Microsoft.Testing.Extensions.VSTestBridge.dll + + + ..\packages\Microsoft.Testing.Platform.1.4.3\lib\netstandard2.0\Microsoft.Testing.Platform.dll + + + ..\packages\Microsoft.Testing.Platform.MSBuild.1.4.3\lib\netstandard2.0\Microsoft.Testing.Platform.MSBuild.dll + + + ..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.TestPlatform.CoreUtilities.dll + + + ..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.TestPlatform.PlatformAbstractions.dll + + + ..\packages\Microsoft.TestPlatform.ObjectModel.17.12.0\lib\net462\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll + + + ..\packages\NuGet.Frameworks.6.12.1\lib\net472\NuGet.Frameworks.dll + - - - 3.5 - - - - - + + ..\packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll + + + ..\packages\System.Collections.Immutable.9.0.0\lib\net462\System.Collections.Immutable.dll + + + + + ..\packages\System.Diagnostics.DiagnosticSource.9.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Memory.4.6.0\lib\net462\System.Memory.dll + + + + + ..\packages\System.Numerics.Vectors.4.6.0\lib\net462\System.Numerics.Vectors.dll + + + ..\packages\System.Reflection.Metadata.9.0.0\lib\net462\System.Reflection.Metadata.dll + + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.1.0\lib\net462\System.Runtime.CompilerServices.Unsafe.dll + + - - - ..\packages\xunit.1.9.0.1566\lib\xunit.dll + + ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll + + + ..\packages\xunit.assert.2.9.2\lib\netstandard1.1\xunit.assert.dll + + + ..\packages\xunit.extensibility.core.2.9.2\lib\net452\xunit.core.dll + + + ..\packages\xunit.extensibility.execution.2.9.2\lib\net452\xunit.execution.desktop.dll - - False - - - + + Properties\SharedVersionInfo.cs + @@ -66,27 +131,40 @@ - + + - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1} + {15eadec7-be27-4334-ba95-0ff3f6bd8a78} Humpback.Interfaces - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3} + {e7feaf88-d6c7-4804-9950-e5f21c1d5811} Humpback - + + - - + + \ No newline at end of file diff --git a/Humpback.Tests/ILLink/ILLink.Descriptors.LibraryBuild.xml b/Humpback.Tests/ILLink/ILLink.Descriptors.LibraryBuild.xml new file mode 100644 index 0000000..a42d7f0 --- /dev/null +++ b/Humpback.Tests/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Humpback.Tests/Impl/TestFileWriter.cs b/Humpback.Tests/Impl/TestFileWriter.cs index a573e70..cf147ce 100644 --- a/Humpback.Tests/Impl/TestFileWriter.cs +++ b/Humpback.Tests/Impl/TestFileWriter.cs @@ -1,20 +1,24 @@ -using System; -using Humpback.Interfaces; +using Humpback.Interfaces; +using System; -namespace Humpback.Tests.Impl { - public class TestFileWriter:IFileWriter { - public void WriteFile(string path, string contents) { +namespace Humpback.Tests.Impl +{ + public class TestFileWriter : IFileWriter + { + public void WriteFile(string path, string contents) + { FileContents += contents; FileName += path; Console.WriteLine(path); } - public bool FileExists(string path) { + public bool FileExists(string path) + { return false; } public string FileName { get; private set; } public string FileContents { get; private set; } - + } } diff --git a/Humpback.Tests/Impl/TestSQLDatabaseProvider.cs b/Humpback.Tests/Impl/TestSQLDatabaseProvider.cs index 48c4ed7..52e6f28 100644 --- a/Humpback.Tests/Impl/TestSQLDatabaseProvider.cs +++ b/Humpback.Tests/Impl/TestSQLDatabaseProvider.cs @@ -1,17 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Humpback.ConfigurationOptions; +using Humpback.ConfigurationOptions; using Humpback.Interfaces; using Humpback.Parts; -namespace Humpback.Tests.Impl { - public class TestSQLDatabaseProvider : SQLDatabaseProvider { - public TestSQLDatabaseProvider(Configuration configuration, Settings settings, ISqlFormatter sql_formatter) : base(configuration, settings, sql_formatter) { +namespace Humpback.Tests.Impl +{ + public class TestSQLDatabaseProvider : SQLDatabaseProvider + { + public TestSQLDatabaseProvider(Configuration configuration, Settings settings, ISqlFormatter sql_formatter) : base(configuration, settings, sql_formatter) + { } - protected override int ExecuteCommand(string command) { + protected override int ExecuteCommand(string command) + { LastCommand = command; return 0; } @@ -19,45 +19,61 @@ protected override int ExecuteCommand(string command) { public string LastCommand { get; private set; } - public new virtual int ExecuteUpCommand(dynamic up) { + public new virtual int ExecuteUpCommand(dynamic up) + { var sql = _sql_formatter.GenerateSQLUp(up); // test for file bool has_filesmo = false; - try { + try + { bool fsmo = up.up.filesmo != null; has_filesmo = true; - } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) { + } + catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) + { // intentionally let thru, no smo object } - if (has_filesmo) { + if (has_filesmo) + { LastCommand = sql[0]; - } else { - - foreach (var s in sql) { + } + else + { - LastCommand += s; - } + foreach (var s in sql) + { + + LastCommand += s; + } } return 1; } - public new virtual int ExecuteDownCommand(dynamic down) { + public new virtual int ExecuteDownCommand(dynamic down) + { var sql = _sql_formatter.GenerateSQLDown(down); // test for file bool has_filesmo = false; - try { + try + { bool fsmo = down.down.filesmo != null; has_filesmo = true; - } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) { + } + catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) + { // intentionally let thru, no smo object } - if (has_filesmo) { + if (has_filesmo) + { LastCommand = sql[0]; - } else { + } + else + { - foreach (var s in sql) { + foreach (var s in sql) + { LastCommand += s; } diff --git a/Humpback.Tests/Properties/AssemblyInfo.cs b/Humpback.Tests/Properties/AssemblyInfo.cs index ebafb0d..34c76a4 100644 --- a/Humpback.Tests/Properties/AssemblyInfo.cs +++ b/Humpback.Tests/Properties/AssemblyInfo.cs @@ -1,10 +1,6 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +using System.Reflection; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. [assembly: AssemblyTitle("Humpback.Tests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] @@ -14,22 +10,6 @@ [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("43ea995a-767b-499d-9628-3566ac6b60fc")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: Guid("6e00dc4b-ef35-41f3-9553-ce3f867f6ae6")] \ No newline at end of file diff --git a/Humpback.Tests/SQLGeneratorTests.cs b/Humpback.Tests/SQLGeneratorTests.cs index 121da90..393923a 100644 --- a/Humpback.Tests/SQLGeneratorTests.cs +++ b/Humpback.Tests/SQLGeneratorTests.cs @@ -1,19 +1,19 @@ -using System; -using System.Text; -using System.Collections.Generic; -using System.Linq; -using Humpback.ConfigurationOptions; +using Humpback.ConfigurationOptions; using Humpback.Interfaces; using Humpback.Parts; using Humpback.Tests.Impl; using Xunit; -namespace Humpback.Tests { - public class SQLGeneratorTests { +namespace Humpback.Tests +{ + public class SQLGeneratorTests + { - private static Settings Settings { - get { + private static Settings Settings + { + get + { return TestHelpers.TestSettings; } @@ -21,7 +21,8 @@ private static Settings Settings { [Fact] - public void TestGeneratePlainSQLString() { + public void TestGeneratePlainSQLString() + { var json = "{\"up\":\"DELETE FROM [Control] WHERE ControlName LIKE '%Date Label'\"}"; @@ -38,7 +39,8 @@ public void TestGeneratePlainSQLString() { } [Fact] - public void TestGeneratePlainSQLStringArray() { + public void TestGeneratePlainSQLStringArray() + { var json = "{\"up\":[\"DELETE FROM [Control] WHERE ControlName LIKE '%Date Label'\",\"DELETE FROM [Control] WHERE ControlName LIKE '%Date Label'\"]}"; @@ -59,7 +61,8 @@ public void TestGeneratePlainSQLStringArray() { [Fact] - public void TestGeneratePlainSQLStringDown() { + public void TestGeneratePlainSQLStringDown() + { var json = "{\"down\":\"DELETE FROM [Control] WHERE ControlName LIKE '%Date Label'\"}"; @@ -76,9 +79,9 @@ public void TestGeneratePlainSQLStringDown() { } [Fact] - public void TestGeneratePlainSQLStringArrayDown() { + public void TestGeneratePlainSQLStringArrayDown() + { var json = "{\"down\":[\"DELETE FROM [Control] WHERE ControlName LIKE '%Date Label'\",\"DELETE FROM [Control] WHERE ControlName LIKE '%Date Label'\"]}"; - //json = "{\"down\":[\"DELETE FROM [Control] WHERE ControlName = 'Facebook Status'\",\"DELETE FROM [ControlType] WHERE ControlTypeName = 'Facebook'\"]}"; Configuration configuration = new Configuration(new[] { "-s", "1" }); TestFileWriter file_writer = new TestFileWriter(); diff --git a/Humpback.Tests/SQLServerFormatterTest.cs b/Humpback.Tests/SQLServerFormatterTest.cs index c3e03cb..ab15d25 100644 --- a/Humpback.Tests/SQLServerFormatterTest.cs +++ b/Humpback.Tests/SQLServerFormatterTest.cs @@ -1,22 +1,27 @@ -using System.Collections.Generic; -using System.IO; +using Humpback.ConfigurationOptions; +using Humpback.Interfaces; using Humpback.Parts; using Humpback.Tests.Impl; using System; -using Humpback.ConfigurationOptions; -using Humpback.Interfaces; +using System.Collections.Generic; using Xunit; namespace Humpback.Tests { - public class SQLServerFormatterTest { + public class SQLServerFormatterTest + { - private static Settings Settings {get { - return TestHelpers.TestSettings; + private static Settings Settings + { + get + { + return TestHelpers.TestSettings; - }} + } + } [Fact] - public void SqlFormatterAddTableTest() { + public void SqlFormatterAddTableTest() + { Configuration configuration = new Configuration(new[] { "-s", "1" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -33,9 +38,10 @@ public void SqlFormatterAddTableTest() { Assert.True(file_writer.FileContents.Contains("Id")); Assert.True(file_writer.FileContents.Contains("PRIMARY KEY")); } - + [Fact] - public void SqlFormatterAddTableTestWithNullableAndDefault() { + public void SqlFormatterAddTableTestWithNullableAndDefault() + { Configuration configuration = new Configuration(new[] { "-s", "11" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -54,7 +60,8 @@ public void SqlFormatterAddTableTestWithNullableAndDefault() { Assert.True(file_writer.FileContents.Contains("[first_name] nvarchar(255) NOT NULL DEFAULT ('JASON')")); } [Fact] - public void SqlFormatterDropTableTest() { + public void SqlFormatterDropTableTest() + { Configuration configuration = new Configuration(new[] { "-s", "2" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -68,7 +75,8 @@ public void SqlFormatterDropTableTest() { } [Fact] - public void SqlFormatterDrop2TableTest() { + public void SqlFormatterDrop2TableTest() + { Configuration configuration = new Configuration(new[] { "-s", "8" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -84,7 +92,8 @@ public void SqlFormatterDrop2TableTest() { } [Fact] - public void SqlFormatterAddColumnTest() { + public void SqlFormatterAddColumnTest() + { Configuration configuration = new Configuration(new[] { "-s", "3" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -98,9 +107,10 @@ public void SqlFormatterAddColumnTest() { Assert.True(file_writer.FileContents.Contains("ADD [name]")); Assert.True(file_writer.FileContents.Contains("nvarchar(255)")); } - + [Fact] - public void SqlFormatterAddColumnReferenceTest() { + public void SqlFormatterAddColumnReferenceTest() + { Configuration configuration = new Configuration(new[] { "-s", "9" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -114,10 +124,11 @@ public void SqlFormatterAddColumnReferenceTest() { Assert.True(file_writer.FileContents.Contains("ALTER TABLE [Orders] ADD [UserId] INT NOT NULL")); Assert.True(file_writer.FileContents.Contains("ALTER TABLE [Orders] ADD CONSTRAINT [FK_orders_user_userid] FOREIGN KEY ([UserId]) REFERENCES [User] ([Id]) ON DELETE NO ACTION ON UPDATE NO ACTION")); } - + [Fact] - public void SqlFormatterAddTableReferenceTest() { + public void SqlFormatterAddTableReferenceTest() + { Configuration configuration = new Configuration(new[] { "-s", "10" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -136,7 +147,8 @@ public void SqlFormatterAddTableReferenceTest() { [Fact] - public void SqlFormatterChangeColumnTest() { + public void SqlFormatterChangeColumnTest() + { Configuration configuration = new Configuration(new[] { "-s", "4" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -151,7 +163,8 @@ public void SqlFormatterChangeColumnTest() { Assert.True(file_writer.FileContents.Contains("nvarchar(255)")); } [Fact] - public void SqlFormatterDropColumnTest() { + public void SqlFormatterDropColumnTest() + { Configuration configuration = new Configuration(new[] { "-s", "5" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -165,7 +178,8 @@ public void SqlFormatterDropColumnTest() { Assert.True(file_writer.FileContents.Contains("DROP COLUMN [name]")); } [Fact] - public void SqlFormatterAddIndexTest() { + public void SqlFormatterAddIndexTest() + { Configuration configuration = new Configuration(new[] { "-s", "6" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -178,7 +192,8 @@ public void SqlFormatterAddIndexTest() { Assert.True(file_writer.FileContents.Contains("CREATE NONCLUSTERED INDEX [IX_categories_title_slug] ON [categories] ( [title] ASC, [slug] ASC )")); } [Fact] - public void SqlFormatterDropIndexTest() { + public void SqlFormatterDropIndexTest() + { Configuration configuration = new Configuration(new[] { "-s", "7" }); TestFileWriter file_writer = new TestFileWriter(); ISqlFormatter formatter = new SQLServerFormatter(configuration, Settings); @@ -192,41 +207,50 @@ public void SqlFormatterDropIndexTest() { } } - public class TestMigrationProvider:IMigrationProvider { - public SortedDictionary GetMigrations() { + public class TestMigrationProvider : IMigrationProvider + { + public SortedDictionary GetMigrations() + { var rv = new SortedDictionary(); - foreach (var key in functions_dictionary.Keys) { + foreach (var key in functions_dictionary.Keys) + { rv.Add(key, key + "xxx.sql"); } return rv; } - public SortedDictionary GetMigrationsContents() { + public SortedDictionary GetMigrationsContents() + { var rv = new SortedDictionary(); - foreach(var key in functions_dictionary.Keys) { + foreach (var key in functions_dictionary.Keys) + { rv.Add(key, functions_dictionary[key]().Value); } return rv; } - public KeyValuePair GetMigrationWithContents(int migration_number) { - if (functions_dictionary.ContainsKey(migration_number)) { + public KeyValuePair GetMigrationWithContents(int migration_number) + { + if (functions_dictionary.ContainsKey(migration_number)) + { return functions_dictionary[migration_number](); } return functions_dictionary[1](); } private int migration_number = 0; - public int DatabaseMigrationNumber() { + public int DatabaseMigrationNumber() + { return migration_number; } - public void SetMigrationNumber(int number) { + public void SetMigrationNumber(int number) + { migration_number = number; } - private readonly Dictionary>> functions_dictionary = - new Dictionary>> { + private readonly Dictionary>> functions_dictionary = + new Dictionary>> { {1, CreateTable}, {2, DropTable}, {3, AddColumns}, @@ -242,41 +266,52 @@ public void SetMigrationNumber(int number) { - private static KeyValuePair CreateTable() { + private static KeyValuePair CreateTable() + { return new KeyValuePair("7xxx.sql", @"{'up':{'create_table':{'name':'tname','timestamps':true,'columns':[{'name':'first_name','type':'string'},{'name':'last_name','type':'money'}]}},'down':{'drop_table':'tname'}}"); } - private static KeyValuePair DropTable() { + private static KeyValuePair DropTable() + { return new KeyValuePair("7xxx.sql", @"{'up':{'drop_table':'tname'}}"); } - private static KeyValuePair Drop2Tables() { + private static KeyValuePair Drop2Tables() + { return new KeyValuePair("7xxx.sql", @"{'up':[{'drop_table':'tname1'},{'drop_table':'tname2'}]}"); } - private static KeyValuePair AddColumns() { + private static KeyValuePair AddColumns() + { return new KeyValuePair("7xxx.sql", @"{'up':{'add_column':{'table':'tname','columns':[{'name':'name','type':'string'}]}},'down':{'remove_column':{'table':'tname','column':'name'}}}"); } - private static KeyValuePair RemoveColumn() { + private static KeyValuePair RemoveColumn() + { return new KeyValuePair("7xxx.sql", @"{'up':{'remove_column':{'table':'tname','column':'name'}}}"); } - private static KeyValuePair ChangeColumns() { + private static KeyValuePair ChangeColumns() + { return new KeyValuePair("7xxx.sql", @"{'up':{'change_column':{'table':'tname','columns':[{'name':'name','type':'string'}]}}}"); } - private static KeyValuePair AddIndex() { + private static KeyValuePair AddIndex() + { return new KeyValuePair("7xxx.sql", @"{'up':{add_index:{table_name:'categories',columns:['title','slug']}}}"); } - private static KeyValuePair RemoveIndex() { + private static KeyValuePair RemoveIndex() + { return new KeyValuePair("7xxx.sql", @"{'up':{remove_index:{table_name:'categories',columns:['title','slug']}}}"); } - private static KeyValuePair AddColumnReference() { + private static KeyValuePair AddColumnReference() + { return new KeyValuePair("7xxx.sql", @"{'up': {'add_column': {'table': 'Orders','columns': [{'name': 'User','type': 'reference'}]}},'down': {'remove_column': {'table': 'Orders','column': 'UserId'}}}"); } - private static KeyValuePair AddTableTwoReference() { + private static KeyValuePair AddTableTwoReference() + { return new KeyValuePair("7xxx.sql", @"{'up': {'create_table': {'name': 'ApplicationControl','timestamps': true,'columns': [{'name': 'name','type': 'string'},{'name': 'ApplicationPage','type': 'reference'},{'name': 'Application','type': 'reference'}]}},'down': {'drop_table': 'ApplicationControl'}}"); } - private static KeyValuePair CreateTableWithNullAndDefault() { + private static KeyValuePair CreateTableWithNullAndDefault() + { return new KeyValuePair("7xxx.sql", @"{'up':{'create_table':{'name':'tname','timestamps':true,'columns':[{'name':'first_name','type':'string', 'nullable':false, default:""'JASON'""},{'name':'last_name','type':'money'}]}},'down':{'drop_table':'tname'}}"); } - + } } diff --git a/Humpback.Tests/Test References/Hump.accessor b/Humpback.Tests/Test References/Hump.accessor deleted file mode 100644 index c6ec315..0000000 --- a/Humpback.Tests/Test References/Hump.accessor +++ /dev/null @@ -1,2 +0,0 @@ -Hump.exe -Desktop diff --git a/Humpback.Tests/TestHelpers.cs b/Humpback.Tests/TestHelpers.cs index 6935936..6465e09 100644 --- a/Humpback.Tests/TestHelpers.cs +++ b/Humpback.Tests/TestHelpers.cs @@ -1,22 +1,24 @@ -using System; -using System.Collections.Generic; +using Humpback.ConfigurationOptions; +using System; using System.IO; -using System.Linq; -using System.Text; -using Humpback.ConfigurationOptions; -namespace Humpback.Tests { - public static class TestHelpers { - public static Settings TestSettings { - get { - var project = new Project { - name="default", +namespace Humpback.Tests +{ + public static class TestHelpers + { + public static Settings TestSettings + { + get + { + var project = new Project + { + name = "default", connection_string = "server=.;database=northwind;Integrated Security=True;", directory = Path.Combine(Environment.CurrentDirectory, "db"), flavor = "sqlserver" }; return new Settings("default", - new [] { project }); + new[] { project }); } } diff --git a/Humpback.Tests/app.config b/Humpback.Tests/app.config new file mode 100644 index 0000000..f0391df --- /dev/null +++ b/Humpback.Tests/app.config @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Humpback.Tests/packages.config b/Humpback.Tests/packages.config index 9394583..c83e4c7 100644 --- a/Humpback.Tests/packages.config +++ b/Humpback.Tests/packages.config @@ -1,4 +1,27 @@  - + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Humpback.sln b/Humpback.sln index 3afaa49..cae0c39 100644 --- a/Humpback.sln +++ b/Humpback.sln @@ -1,71 +1,48 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Humpback", "Humpback\Humpback.csproj", "{2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}" +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34309.116 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Humpback", "Humpback\Humpback.csproj", "{E7FEAF88-D6C7-4804-9950-E5F21C1D5811}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Humpback.Tests", "Humpback.Tests\Humpback.Tests.csproj", "{0973A5D4-8B5B-4FFB-89E3-F8E42613D680}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Humpback.Interfaces", "Humpback.Interfaces\Humpback.Interfaces.csproj", "{15EADEC7-BE27-4334-BA95-0FF3F6BD8A78}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5CC74F4A-4CAA-4124-8FC2-8F7B6F17B6EA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Humpback.Smo", "Humpback.Smo\Humpback.Smo.csproj", "{804678AE-B193-4A4E-ADE7-B02B66361F73}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Humpback.Interfaces", "Humpback.Interfaces\Humpback.Interfaces.csproj", "{B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Humpback.Tests", "Humpback.Tests\Humpback.Tests.csproj", "{6E00DC4B-EF35-41F3-9553-CE3F867F6AE6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Humpback.Smo", "Humpback.Smo\Humpback.Smo.csproj", "{347115FF-034F-4257-B873-88C4B6D42FDC}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{90DAD459-602D-4E95-9231-65E6F75BFBEC}" + ProjectSection(SolutionItems) = preProject + SharedVersionInfo.cs = SharedVersionInfo.cs + EndProjectSection EndProject Global - GlobalSection(TestCaseManagementSettings) = postSolution - CategoryFile = Humpback.vsmdi - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Debug|Any CPU.ActiveCfg = Debug|x86 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Debug|x86.ActiveCfg = Debug|x86 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Debug|x86.Build.0 = Debug|x86 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Release|Any CPU.ActiveCfg = Release|x86 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Release|Mixed Platforms.Build.0 = Release|x86 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Release|x86.ActiveCfg = Release|x86 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3}.Release|x86.Build.0 = Release|x86 - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Debug|x86.ActiveCfg = Debug|Any CPU - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Release|Any CPU.Build.0 = Release|Any CPU - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {0973A5D4-8B5B-4FFB-89E3-F8E42613D680}.Release|x86.ActiveCfg = Release|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Debug|x86.ActiveCfg = Debug|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Release|Any CPU.Build.0 = Release|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1}.Release|x86.ActiveCfg = Release|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Debug|x86.ActiveCfg = Debug|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Release|Any CPU.Build.0 = Release|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {347115FF-034F-4257-B873-88C4B6D42FDC}.Release|x86.ActiveCfg = Release|Any CPU + {E7FEAF88-D6C7-4804-9950-E5F21C1D5811}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7FEAF88-D6C7-4804-9950-E5F21C1D5811}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7FEAF88-D6C7-4804-9950-E5F21C1D5811}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7FEAF88-D6C7-4804-9950-E5F21C1D5811}.Release|Any CPU.Build.0 = Release|Any CPU + {15EADEC7-BE27-4334-BA95-0FF3F6BD8A78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15EADEC7-BE27-4334-BA95-0FF3F6BD8A78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {15EADEC7-BE27-4334-BA95-0FF3F6BD8A78}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15EADEC7-BE27-4334-BA95-0FF3F6BD8A78}.Release|Any CPU.Build.0 = Release|Any CPU + {804678AE-B193-4A4E-ADE7-B02B66361F73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {804678AE-B193-4A4E-ADE7-B02B66361F73}.Debug|Any CPU.Build.0 = Debug|Any CPU + {804678AE-B193-4A4E-ADE7-B02B66361F73}.Release|Any CPU.ActiveCfg = Release|Any CPU + {804678AE-B193-4A4E-ADE7-B02B66361F73}.Release|Any CPU.Build.0 = Release|Any CPU + {6E00DC4B-EF35-41F3-9553-CE3F867F6AE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6E00DC4B-EF35-41F3-9553-CE3F867F6AE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6E00DC4B-EF35-41F3-9553-CE3F867F6AE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6E00DC4B-EF35-41F3-9553-CE3F867F6AE6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {86269D65-173C-4EC3-A223-D17F1D9C4956} + EndGlobalSection EndGlobal diff --git a/Humpback/Artifacts/Humpback.Smo.dll b/Humpback/Artifacts/Humpback.Smo.dll deleted file mode 100644 index 509c7c9..0000000 Binary files a/Humpback/Artifacts/Humpback.Smo.dll and /dev/null differ diff --git a/Humpback/ConfigurationOptions/Configuration.cs b/Humpback/ConfigurationOptions/Configuration.cs index 39f89f6..9679ef1 100644 --- a/Humpback/ConfigurationOptions/Configuration.cs +++ b/Humpback/ConfigurationOptions/Configuration.cs @@ -1,43 +1,48 @@ using System; using System.Collections.Generic; -using System.Diagnostics; -using System.IO; using System.Linq; -using System.Configuration; -namespace Humpback.ConfigurationOptions { - public class Configuration { +namespace Humpback.ConfigurationOptions +{ + public class Configuration + { - private void Parse(IEnumerable options) { + private void Parse(IEnumerable options) + { var oset = new OptionSet() .Add("?|help|h|HELP|H|Help", h => WriteHelp = true) .Add("g=|gen=|G=|GEN=|Gen=|Generate=|generate=|GENERATE=", - s => { + s => + { SetMainToFalse(); Generate = true; GenerateString = s.Trim(); }) .Add("l:|list:|L:|LIST:|List:", - s => { + s => + { SetMainToFalse(); List = true; }) .Add("m:|migrate:|M:|MIGRATE:|Migrate:", - s => { + s => + { SetMainToFalse(); Migrate = true; }) .Add("s:|sql:|S:|SQL:|Sql:", - s => { + s => + { SetMainToFalse(); Sql = true; }) .Add("f:|file:|F:|File:|FILE:", - s => { + s => + { SetMainToFalse(); File = true; }) - .Add("e|E|ENV|env|Env", e => {SetMainToFalse();Env = true;}) + .Add("e|E|ENV|env|Env", e => { SetMainToFalse(); Env = true; }) .Add("all", a => All = true) .Add("single", s => Single = true) .Add("dp", dp => Deployed = true) @@ -48,7 +53,7 @@ private void Parse(IEnumerable options) { .Add("empty", e => Empty = true) .Add("reset", r => Reset = true) .Add("v", v => Verbose = true) - .Add("dir=", s => settings_dir=s) + .Add("dir=", s => settings_dir = s) .Add("cs=", s => settings_cs = s) .Add("flavor=", s => settings_flavor = s) .Add("rename=", s => settings_rename = s) @@ -57,7 +62,7 @@ private void Parse(IEnumerable options) { .Add("init", s => env_init = true) .Add("remove=", s => remove_project_name = s) ; - + Extra = oset.Parse(options); } @@ -73,13 +78,16 @@ private void Parse(IEnumerable options) { - public Configuration() { + public Configuration() + { ResetOptions(); } public Configuration(IEnumerable options) - : this() { - if (options == null || options.Count() == 0) { + : this() + { + if (options == null || options.Count() == 0) + { return; } Parse(options); @@ -87,14 +95,16 @@ public Configuration(IEnumerable options) - public string NextSerialNumber() { + public string NextSerialNumber() + { return DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmss"); } - - private void ResetOptions() { + + private void ResetOptions() + { WriteHelp = true; Generate = false; List = false; @@ -105,7 +115,8 @@ private void ResetOptions() { SetMigrateToLatestVersion(); GenerateString = ""; } - private void SetMainToFalse() { + private void SetMainToFalse() + { WriteHelp = false; Generate = false; List = false; @@ -115,7 +126,8 @@ private void SetMainToFalse() { File = false; } - private void SetMigrateToLatestVersion() { + private void SetMigrateToLatestVersion() + { MigrateToVersion = 0; } @@ -155,18 +167,21 @@ private void SetMigrateToLatestVersion() { - public bool Verbose { + public bool Verbose + { get; set; } } - public enum GenerateActionType { + public enum GenerateActionType + { Empty, AddTable, RemoveTable, AddColumn, ChangeColumn, RemoveColumn, AddIndex, RemoveIndex, Sql, File, FileSmo } - public enum RunActionType { + public enum RunActionType + { Up, Down } } diff --git a/Humpback/ConfigurationOptions/Help.cs b/Humpback/ConfigurationOptions/Help.cs index 0009c9f..70fb486 100644 --- a/Humpback/ConfigurationOptions/Help.cs +++ b/Humpback/ConfigurationOptions/Help.cs @@ -1,41 +1,59 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -namespace Humpback.ConfigurationOptions { - public class Help : IHumpbackCommand { +namespace Humpback.ConfigurationOptions +{ + public class Help : IHumpbackCommand + { private Configuration _configuration; - public Help(Configuration configuration) { + public Help(Configuration configuration) + { _configuration = configuration; } - public void Execute() { - string flag = (_configuration.Extra!=null && _configuration.Extra.Any()) ? _configuration.Extra.First() : ""; + public void Execute() + { + string flag = (_configuration.Extra != null && _configuration.Extra.Any()) ? _configuration.Extra.First() : ""; flag = flag.ToUpperInvariant(); - if (string.IsNullOrWhiteSpace(flag)) { + if (string.IsNullOrWhiteSpace(flag)) + { write_general_help(); - } else if ("GENERATE".StartsWith(flag)) { + } + else if ("GENERATE".StartsWith(flag)) + { write_generate_help(); - } else if ("LIST".StartsWith(flag)) { + } + else if ("LIST".StartsWith(flag)) + { write_list_help(); - } else if ("FILE".StartsWith(flag)) { + } + else if ("FILE".StartsWith(flag)) + { write_edit_file_help(); - } else if ("MIGRATE".StartsWith(flag)) { + } + else if ("MIGRATE".StartsWith(flag)) + { write_migrate_help(); - } else if ("SQL".StartsWith(flag)) { + } + else if ("SQL".StartsWith(flag)) + { write_sql_help(); - } else if ("ENVIRONMENT".StartsWith(flag)) { + } + else if ("ENVIRONMENT".StartsWith(flag)) + { write_environment_help(); - } else { + } + else + { write_general_help(); } } - private static void write_generate_help() { + private static void write_generate_help() + { Console.WriteLine(@" Humpback Migration Information ============================== @@ -90,7 +108,8 @@ column names are required to be able to generate the index name "); } - private static void write_list_help() { + private static void write_list_help() + { Console.WriteLine(@" Humpback Migration Information ============================== @@ -106,7 +125,8 @@ List Migrations and Details } - private static void write_edit_file_help() { + private static void write_edit_file_help() + { Console.WriteLine(@" Humpback Migration Information ============================== @@ -119,7 +139,8 @@ Edit Migration Text File } - private static void write_migrate_help() { + private static void write_migrate_help() + { Console.WriteLine(@" Humpback Migration Information ============================== @@ -138,7 +159,8 @@ Executes Migrations against the database. "); } - private static void write_sql_help() { + private static void write_sql_help() + { Console.WriteLine(@" Humpback Migration Information ============================== @@ -160,7 +182,8 @@ Generates Sql files based on migrations. "); } - private static void write_environment_help() { + private static void write_environment_help() + { Console.WriteLine(@" Humpback Migration Information ============================== @@ -188,7 +211,8 @@ You may prefer to configure settings from the command line. } - private static void write_general_help() { + private static void write_general_help() + { Console.WriteLine(@" Humpback Migration Information ============================== diff --git a/Humpback/ConfigurationOptions/Options.cs b/Humpback/ConfigurationOptions/Options.cs index 40666b0..5eb317c 100644 --- a/Humpback/ConfigurationOptions/Options.cs +++ b/Humpback/ConfigurationOptions/Options.cs @@ -134,551 +134,582 @@ using System.Text; using System.Text.RegularExpressions; -namespace Humpback.ConfigurationOptions { - - public class OptionValueCollection : IList, IList { - - List values = new List (); - OptionContext c; - - internal OptionValueCollection (OptionContext c) - { - this.c = c; - } - - #region ICollection - void ICollection.CopyTo (Array array, int index) {(values as ICollection).CopyTo (array, index);} - bool ICollection.IsSynchronized {get {return (values as ICollection).IsSynchronized;}} - object ICollection.SyncRoot {get {return (values as ICollection).SyncRoot;}} - #endregion - - #region ICollection - public void Add (string item) {values.Add (item);} - public void Clear () {values.Clear ();} - public bool Contains (string item) {return values.Contains (item);} - public void CopyTo (string[] array, int arrayIndex) {values.CopyTo (array, arrayIndex);} - public bool Remove (string item) {return values.Remove (item);} - public int Count {get {return values.Count;}} - public bool IsReadOnly {get {return false;}} - #endregion - - #region IEnumerable - IEnumerator IEnumerable.GetEnumerator () {return values.GetEnumerator ();} - #endregion - - #region IEnumerable - public IEnumerator GetEnumerator () {return values.GetEnumerator ();} - #endregion - - #region IList - int IList.Add (object value) {return (values as IList).Add (value);} - bool IList.Contains (object value) {return (values as IList).Contains (value);} - int IList.IndexOf (object value) {return (values as IList).IndexOf (value);} - void IList.Insert (int index, object value) {(values as IList).Insert (index, value);} - void IList.Remove (object value) {(values as IList).Remove (value);} - void IList.RemoveAt (int index) {(values as IList).RemoveAt (index);} - bool IList.IsFixedSize {get {return false;}} - object IList.this [int index] {get {return this [index];} set {(values as IList)[index] = value;}} - #endregion - - #region IList - public int IndexOf (string item) {return values.IndexOf (item);} - public void Insert (int index, string item) {values.Insert (index, item);} - public void RemoveAt (int index) {values.RemoveAt (index);} - - private void AssertValid (int index) - { - if (c.Option == null) - throw new InvalidOperationException ("OptionContext.Option is null."); - if (index >= c.Option.MaxValueCount) - throw new ArgumentOutOfRangeException ("index"); - if (c.Option.OptionValueType == OptionValueType.Required && - index >= values.Count) - throw new OptionException (string.Format ( - c.OptionSet.MessageLocalizer ("Missing required value for option '{0}'."), c.OptionName), - c.OptionName); - } - - public string this [int index] { - get { - AssertValid (index); - return index >= values.Count ? null : values [index]; - } - set { - values [index] = value; - } - } - #endregion - - public List ToList () - { - return new List (values); - } - - public string[] ToArray () - { - return values.ToArray (); - } - - public override string ToString () - { - return string.Join (", ", values.ToArray ()); - } - } - - public class OptionContext { - private Option option; - private string name; - private int index; - private OptionSet set; - private OptionValueCollection c; - - public OptionContext (OptionSet set) - { - this.set = set; - this.c = new OptionValueCollection (this); - } - - public Option Option { - get {return option;} - set {option = value;} - } - - public string OptionName { - get {return name;} - set {name = value;} - } - - public int OptionIndex { - get {return index;} - set {index = value;} - } - - public OptionSet OptionSet { - get {return set;} - } - - public OptionValueCollection OptionValues { - get {return c;} - } - } - - public enum OptionValueType { - None, - Optional, - Required, - } - - public abstract class Option { - string prototype, description; - string[] names; - OptionValueType type; - int count; - string[] separators; - - protected Option (string prototype, string description) - : this (prototype, description, 1) - { - } - - protected Option (string prototype, string description, int maxValueCount) - { - if (prototype == null) - throw new ArgumentNullException ("prototype"); - if (prototype.Length == 0) - throw new ArgumentException ("Cannot be the empty string.", "prototype"); - if (maxValueCount < 0) - throw new ArgumentOutOfRangeException ("maxValueCount"); - - this.prototype = prototype; - this.names = prototype.Split ('|'); - this.description = description; - this.count = maxValueCount; - this.type = ParsePrototype (); - - if (this.count == 0 && type != OptionValueType.None) - throw new ArgumentException ( - "Cannot provide maxValueCount of 0 for OptionValueType.Required or " + - "OptionValueType.Optional.", - "maxValueCount"); - if (this.type == OptionValueType.None && maxValueCount > 1) - throw new ArgumentException ( - string.Format ("Cannot provide maxValueCount of {0} for OptionValueType.None.", maxValueCount), - "maxValueCount"); - if (Array.IndexOf (names, "<>") >= 0 && - ((names.Length == 1 && this.type != OptionValueType.None) || - (names.Length > 1 && this.MaxValueCount > 1))) - throw new ArgumentException ( - "The default option handler '<>' cannot require values.", - "prototype"); - } - - public string Prototype {get {return prototype;}} - public string Description {get {return description;}} - public OptionValueType OptionValueType {get {return type;}} - public int MaxValueCount {get {return count;}} - - public string[] GetNames () - { - return (string[]) names.Clone (); - } - - public string[] GetValueSeparators () - { - if (separators == null) - return new string [0]; - return (string[]) separators.Clone (); - } - - protected static T Parse (string value, OptionContext c) - { - TypeConverter conv = TypeDescriptor.GetConverter (typeof (T)); - T t = default (T); - try { - if (value != null) - t = (T) conv.ConvertFromString (value); - } - catch (Exception e) { - throw new OptionException ( - string.Format ( - c.OptionSet.MessageLocalizer ("Could not convert string `{0}' to type {1} for option `{2}'."), - value, typeof (T).Name, c.OptionName), - c.OptionName, e); - } - return t; - } - - internal string[] Names {get {return names;}} - internal string[] ValueSeparators {get {return separators;}} - - static readonly char[] NameTerminator = new char[]{'=', ':'}; - - private OptionValueType ParsePrototype () - { - char type = '\0'; - List seps = new List (); - for (int i = 0; i < names.Length; ++i) { - string name = names [i]; - if (name.Length == 0) - throw new ArgumentException ("Empty option names are not supported.", "prototype"); - - int end = name.IndexOfAny (NameTerminator); - if (end == -1) - continue; - names [i] = name.Substring (0, end); - if (type == '\0' || type == name [end]) - type = name [end]; - else - throw new ArgumentException ( - string.Format ("Conflicting option types: '{0}' vs. '{1}'.", type, name [end]), - "prototype"); - AddSeparators (name, end, seps); - } - - if (type == '\0') - return OptionValueType.None; - - if (count <= 1 && seps.Count != 0) - throw new ArgumentException ( - string.Format ("Cannot provide key/value separators for Options taking {0} value(s).", count), - "prototype"); - if (count > 1) { - if (seps.Count == 0) - this.separators = new string[]{":", "="}; - else if (seps.Count == 1 && seps [0].Length == 0) - this.separators = null; - else - this.separators = seps.ToArray (); - } - - return type == '=' ? OptionValueType.Required : OptionValueType.Optional; - } - - private static void AddSeparators (string name, int end, ICollection seps) - { - int start = -1; - for (int i = end+1; i < name.Length; ++i) { - switch (name [i]) { - case '{': - if (start != -1) - throw new ArgumentException ( - string.Format ("Ill-formed name/value separator found in \"{0}\".", name), - "prototype"); - start = i+1; - break; - case '}': - if (start == -1) - throw new ArgumentException ( - string.Format ("Ill-formed name/value separator found in \"{0}\".", name), - "prototype"); - seps.Add (name.Substring (start, i-start)); - start = -1; - break; - default: - if (start == -1) - seps.Add (name [i].ToString ()); - break; - } - } - if (start != -1) - throw new ArgumentException ( - string.Format ("Ill-formed name/value separator found in \"{0}\".", name), - "prototype"); - } - - public void Invoke (OptionContext c) - { - OnParseComplete (c); - c.OptionName = null; - c.Option = null; - c.OptionValues.Clear (); - } - - protected abstract void OnParseComplete (OptionContext c); - - public override string ToString () - { - return Prototype; - } - } - - [Serializable] - public class OptionException : Exception { - private string option; - - public OptionException () - { - } - - public OptionException (string message, string optionName) - : base (message) - { - this.option = optionName; - } - - public OptionException (string message, string optionName, Exception innerException) - : base (message, innerException) - { - this.option = optionName; - } - - protected OptionException (SerializationInfo info, StreamingContext context) - : base (info, context) - { - this.option = info.GetString ("OptionName"); - } - - public string OptionName { - get {return this.option;} - } - - [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)] - public override void GetObjectData (SerializationInfo info, StreamingContext context) - { - base.GetObjectData (info, context); - info.AddValue ("OptionName", option); - } - } - - public delegate void OptionAction (TKey key, TValue value); - - public class OptionSet : KeyedCollection - { - public OptionSet () - : this (delegate (string f) {return f;}) - { - } - - public OptionSet (Converter localizer) - { - this.localizer = localizer; - } - - Converter localizer; - - public Converter MessageLocalizer { - get {return localizer;} - } - - protected override string GetKeyForItem (Option item) - { - if (item == null) - throw new ArgumentNullException ("option"); - if (item.Names != null && item.Names.Length > 0) - return item.Names [0]; - // This should never happen, as it's invalid for Option to be - // constructed w/o any names. - throw new InvalidOperationException ("Option has no names!"); - } - - [Obsolete ("Use KeyedCollection.this[string]")] - protected Option GetOptionForName (string option) - { - if (option == null) - throw new ArgumentNullException ("option"); - try { - return base [option]; - } - catch (KeyNotFoundException) { - return null; - } - } - - protected override void InsertItem (int index, Option item) - { - base.InsertItem (index, item); - AddImpl (item); - } - - protected override void RemoveItem (int index) - { - base.RemoveItem (index); - Option p = Items [index]; - // KeyedCollection.RemoveItem() handles the 0th item - for (int i = 1; i < p.Names.Length; ++i) { - Dictionary.Remove (p.Names [i]); - } - } - - protected override void SetItem (int index, Option item) - { - base.SetItem (index, item); - RemoveItem (index); - AddImpl (item); - } - - private void AddImpl (Option option) - { - if (option == null) - throw new ArgumentNullException ("option"); - List added = new List (option.Names.Length); - try { - // KeyedCollection.InsertItem/SetItem handle the 0th name. - for (int i = 1; i < option.Names.Length; ++i) { - Dictionary.Add (option.Names [i], option); - added.Add (option.Names [i]); - } - } - catch (Exception) { - foreach (string name in added) - Dictionary.Remove (name); - throw; - } - } - - public new OptionSet Add (Option option) - { - base.Add (option); - return this; - } - - sealed class ActionOption : Option { - Action action; - - public ActionOption (string prototype, string description, int count, Action action) - : base (prototype, description, count) - { - if (action == null) - throw new ArgumentNullException ("action"); - this.action = action; - } - - protected override void OnParseComplete (OptionContext c) - { - action (c.OptionValues); - } - } - - public OptionSet Add (string prototype, Action action) - { - return Add (prototype, null, action); - } - - public OptionSet Add (string prototype, string description, Action action) - { - if (action == null) - throw new ArgumentNullException ("action"); - Option p = new ActionOption (prototype, description, 1, - delegate (OptionValueCollection v) { action (v [0]); }); - base.Add (p); - return this; - } - - public OptionSet Add (string prototype, OptionAction action) - { - return Add (prototype, null, action); - } - - public OptionSet Add (string prototype, string description, OptionAction action) - { - if (action == null) - throw new ArgumentNullException ("action"); - Option p = new ActionOption (prototype, description, 2, - delegate (OptionValueCollection v) {action (v [0], v [1]);}); - base.Add (p); - return this; - } - - sealed class ActionOption : Option { - Action action; - - public ActionOption (string prototype, string description, Action action) - : base (prototype, description, 1) - { - if (action == null) - throw new ArgumentNullException ("action"); - this.action = action; - } - - protected override void OnParseComplete (OptionContext c) - { - action (Parse (c.OptionValues [0], c)); - } - } - - sealed class ActionOption : Option { - OptionAction action; - - public ActionOption (string prototype, string description, OptionAction action) - : base (prototype, description, 2) - { - if (action == null) - throw new ArgumentNullException ("action"); - this.action = action; - } - - protected override void OnParseComplete (OptionContext c) - { - action ( - Parse (c.OptionValues [0], c), - Parse (c.OptionValues [1], c)); - } - } - - public OptionSet Add (string prototype, Action action) - { - return Add (prototype, null, action); - } - - public OptionSet Add (string prototype, string description, Action action) - { - return Add (new ActionOption (prototype, description, action)); - } - - public OptionSet Add (string prototype, OptionAction action) - { - return Add (prototype, null, action); - } - - public OptionSet Add (string prototype, string description, OptionAction action) - { - return Add (new ActionOption (prototype, description, action)); - } - - protected virtual OptionContext CreateOptionContext () - { - return new OptionContext (this); - } +namespace Humpback.ConfigurationOptions +{ + + public class OptionValueCollection : IList, IList + { + + List values = new List(); + OptionContext c; + + internal OptionValueCollection(OptionContext c) + { + this.c = c; + } + + #region ICollection + void ICollection.CopyTo(Array array, int index) { (values as ICollection).CopyTo(array, index); } + bool ICollection.IsSynchronized { get { return (values as ICollection).IsSynchronized; } } + object ICollection.SyncRoot { get { return (values as ICollection).SyncRoot; } } + #endregion + + #region ICollection + public void Add(string item) { values.Add(item); } + public void Clear() { values.Clear(); } + public bool Contains(string item) { return values.Contains(item); } + public void CopyTo(string[] array, int arrayIndex) { values.CopyTo(array, arrayIndex); } + public bool Remove(string item) { return values.Remove(item); } + public int Count { get { return values.Count; } } + public bool IsReadOnly { get { return false; } } + #endregion + + #region IEnumerable + IEnumerator IEnumerable.GetEnumerator() { return values.GetEnumerator(); } + #endregion + + #region IEnumerable + public IEnumerator GetEnumerator() { return values.GetEnumerator(); } + #endregion + + #region IList + int IList.Add(object value) { return (values as IList).Add(value); } + bool IList.Contains(object value) { return (values as IList).Contains(value); } + int IList.IndexOf(object value) { return (values as IList).IndexOf(value); } + void IList.Insert(int index, object value) { (values as IList).Insert(index, value); } + void IList.Remove(object value) { (values as IList).Remove(value); } + void IList.RemoveAt(int index) { (values as IList).RemoveAt(index); } + bool IList.IsFixedSize { get { return false; } } + object IList.this[int index] { get { return this[index]; } set { (values as IList)[index] = value; } } + #endregion + + #region IList + public int IndexOf(string item) { return values.IndexOf(item); } + public void Insert(int index, string item) { values.Insert(index, item); } + public void RemoveAt(int index) { values.RemoveAt(index); } + + private void AssertValid(int index) + { + if (c.Option == null) + throw new InvalidOperationException("OptionContext.Option is null."); + if (index >= c.Option.MaxValueCount) + throw new ArgumentOutOfRangeException("index"); + if (c.Option.OptionValueType == OptionValueType.Required && + index >= values.Count) + throw new OptionException(string.Format( + c.OptionSet.MessageLocalizer("Missing required value for option '{0}'."), c.OptionName), + c.OptionName); + } + + public string this[int index] + { + get + { + AssertValid(index); + return index >= values.Count ? null : values[index]; + } + set + { + values[index] = value; + } + } + #endregion + + public List ToList() + { + return new List(values); + } + + public string[] ToArray() + { + return values.ToArray(); + } + + public override string ToString() + { + return string.Join(", ", values.ToArray()); + } + } + + public class OptionContext + { + private Option option; + private string name; + private int index; + private OptionSet set; + private OptionValueCollection c; + + public OptionContext(OptionSet set) + { + this.set = set; + this.c = new OptionValueCollection(this); + } + + public Option Option + { + get { return option; } + set { option = value; } + } + + public string OptionName + { + get { return name; } + set { name = value; } + } + + public int OptionIndex + { + get { return index; } + set { index = value; } + } + + public OptionSet OptionSet + { + get { return set; } + } + + public OptionValueCollection OptionValues + { + get { return c; } + } + } + + public enum OptionValueType + { + None, + Optional, + Required, + } + + public abstract class Option + { + string prototype, description; + string[] names; + OptionValueType type; + int count; + string[] separators; + + protected Option(string prototype, string description) + : this(prototype, description, 1) + { + } + + protected Option(string prototype, string description, int maxValueCount) + { + if (prototype == null) + throw new ArgumentNullException("prototype"); + if (prototype.Length == 0) + throw new ArgumentException("Cannot be the empty string.", "prototype"); + if (maxValueCount < 0) + throw new ArgumentOutOfRangeException("maxValueCount"); + + this.prototype = prototype; + this.names = prototype.Split('|'); + this.description = description; + this.count = maxValueCount; + this.type = ParsePrototype(); + + if (this.count == 0 && type != OptionValueType.None) + throw new ArgumentException( + "Cannot provide maxValueCount of 0 for OptionValueType.Required or " + + "OptionValueType.Optional.", + "maxValueCount"); + if (this.type == OptionValueType.None && maxValueCount > 1) + throw new ArgumentException( + string.Format("Cannot provide maxValueCount of {0} for OptionValueType.None.", maxValueCount), + "maxValueCount"); + if (Array.IndexOf(names, "<>") >= 0 && + ((names.Length == 1 && this.type != OptionValueType.None) || + (names.Length > 1 && this.MaxValueCount > 1))) + throw new ArgumentException( + "The default option handler '<>' cannot require values.", + "prototype"); + } + + public string Prototype { get { return prototype; } } + public string Description { get { return description; } } + public OptionValueType OptionValueType { get { return type; } } + public int MaxValueCount { get { return count; } } + + public string[] GetNames() + { + return (string[])names.Clone(); + } + + public string[] GetValueSeparators() + { + if (separators == null) + return new string[0]; + return (string[])separators.Clone(); + } + + protected static T Parse(string value, OptionContext c) + { + TypeConverter conv = TypeDescriptor.GetConverter(typeof(T)); + T t = default(T); + try + { + if (value != null) + t = (T)conv.ConvertFromString(value); + } + catch (Exception e) + { + throw new OptionException( + string.Format( + c.OptionSet.MessageLocalizer("Could not convert string `{0}' to type {1} for option `{2}'."), + value, typeof(T).Name, c.OptionName), + c.OptionName, e); + } + return t; + } + + internal string[] Names { get { return names; } } + internal string[] ValueSeparators { get { return separators; } } + + static readonly char[] NameTerminator = new char[] { '=', ':' }; + + private OptionValueType ParsePrototype() + { + char type = '\0'; + List seps = new List(); + for (int i = 0; i < names.Length; ++i) + { + string name = names[i]; + if (name.Length == 0) + throw new ArgumentException("Empty option names are not supported.", "prototype"); + + int end = name.IndexOfAny(NameTerminator); + if (end == -1) + continue; + names[i] = name.Substring(0, end); + if (type == '\0' || type == name[end]) + type = name[end]; + else + throw new ArgumentException( + string.Format("Conflicting option types: '{0}' vs. '{1}'.", type, name[end]), + "prototype"); + AddSeparators(name, end, seps); + } + + if (type == '\0') + return OptionValueType.None; + + if (count <= 1 && seps.Count != 0) + throw new ArgumentException( + string.Format("Cannot provide key/value separators for Options taking {0} value(s).", count), + "prototype"); + if (count > 1) + { + if (seps.Count == 0) + this.separators = new string[] { ":", "=" }; + else if (seps.Count == 1 && seps[0].Length == 0) + this.separators = null; + else + this.separators = seps.ToArray(); + } + + return type == '=' ? OptionValueType.Required : OptionValueType.Optional; + } + + private static void AddSeparators(string name, int end, ICollection seps) + { + int start = -1; + for (int i = end + 1; i < name.Length; ++i) + { + switch (name[i]) + { + case '{': + if (start != -1) + throw new ArgumentException( + string.Format("Ill-formed name/value separator found in \"{0}\".", name), + "prototype"); + start = i + 1; + break; + case '}': + if (start == -1) + throw new ArgumentException( + string.Format("Ill-formed name/value separator found in \"{0}\".", name), + "prototype"); + seps.Add(name.Substring(start, i - start)); + start = -1; + break; + default: + if (start == -1) + seps.Add(name[i].ToString()); + break; + } + } + if (start != -1) + throw new ArgumentException( + string.Format("Ill-formed name/value separator found in \"{0}\".", name), + "prototype"); + } + + public void Invoke(OptionContext c) + { + OnParseComplete(c); + c.OptionName = null; + c.Option = null; + c.OptionValues.Clear(); + } + + protected abstract void OnParseComplete(OptionContext c); + + public override string ToString() + { + return Prototype; + } + } + + [Serializable] + public class OptionException : Exception + { + private string option; + + public OptionException() + { + } + + public OptionException(string message, string optionName) + : base(message) + { + this.option = optionName; + } + + public OptionException(string message, string optionName, Exception innerException) + : base(message, innerException) + { + this.option = optionName; + } + + protected OptionException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + this.option = info.GetString("OptionName"); + } + + public string OptionName + { + get { return this.option; } + } + + [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue("OptionName", option); + } + } + + public delegate void OptionAction(TKey key, TValue value); + + public class OptionSet : KeyedCollection + { + public OptionSet() + : this(delegate (string f) { return f; }) + { + } + + public OptionSet(Converter localizer) + { + this.localizer = localizer; + } + + Converter localizer; + + public Converter MessageLocalizer + { + get { return localizer; } + } + + protected override string GetKeyForItem(Option item) + { + if (item == null) + throw new ArgumentNullException("option"); + if (item.Names != null && item.Names.Length > 0) + return item.Names[0]; + // This should never happen, as it's invalid for Option to be + // constructed w/o any names. + throw new InvalidOperationException("Option has no names!"); + } + + [Obsolete("Use KeyedCollection.this[string]")] + protected Option GetOptionForName(string option) + { + if (option == null) + throw new ArgumentNullException("option"); + try + { + return base[option]; + } + catch (KeyNotFoundException) + { + return null; + } + } + + protected override void InsertItem(int index, Option item) + { + base.InsertItem(index, item); + AddImpl(item); + } + + protected override void RemoveItem(int index) + { + base.RemoveItem(index); + Option p = Items[index]; + // KeyedCollection.RemoveItem() handles the 0th item + for (int i = 1; i < p.Names.Length; ++i) + { + Dictionary.Remove(p.Names[i]); + } + } + + protected override void SetItem(int index, Option item) + { + base.SetItem(index, item); + RemoveItem(index); + AddImpl(item); + } + + private void AddImpl(Option option) + { + if (option == null) + throw new ArgumentNullException("option"); + List added = new List(option.Names.Length); + try + { + // KeyedCollection.InsertItem/SetItem handle the 0th name. + for (int i = 1; i < option.Names.Length; ++i) + { + Dictionary.Add(option.Names[i], option); + added.Add(option.Names[i]); + } + } + catch (Exception) + { + foreach (string name in added) + Dictionary.Remove(name); + throw; + } + } + + public new OptionSet Add(Option option) + { + base.Add(option); + return this; + } + + sealed class ActionOption : Option + { + Action action; + + public ActionOption(string prototype, string description, int count, Action action) + : base(prototype, description, count) + { + if (action == null) + throw new ArgumentNullException("action"); + this.action = action; + } + + protected override void OnParseComplete(OptionContext c) + { + action(c.OptionValues); + } + } + + public OptionSet Add(string prototype, Action action) + { + return Add(prototype, null, action); + } + + public OptionSet Add(string prototype, string description, Action action) + { + if (action == null) + throw new ArgumentNullException("action"); + Option p = new ActionOption(prototype, description, 1, + delegate (OptionValueCollection v) { action(v[0]); }); + base.Add(p); + return this; + } + + public OptionSet Add(string prototype, OptionAction action) + { + return Add(prototype, null, action); + } + + public OptionSet Add(string prototype, string description, OptionAction action) + { + if (action == null) + throw new ArgumentNullException("action"); + Option p = new ActionOption(prototype, description, 2, + delegate (OptionValueCollection v) { action(v[0], v[1]); }); + base.Add(p); + return this; + } + + sealed class ActionOption : Option + { + Action action; + + public ActionOption(string prototype, string description, Action action) + : base(prototype, description, 1) + { + if (action == null) + throw new ArgumentNullException("action"); + this.action = action; + } + + protected override void OnParseComplete(OptionContext c) + { + action(Parse(c.OptionValues[0], c)); + } + } + + sealed class ActionOption : Option + { + OptionAction action; + + public ActionOption(string prototype, string description, OptionAction action) + : base(prototype, description, 2) + { + if (action == null) + throw new ArgumentNullException("action"); + this.action = action; + } + + protected override void OnParseComplete(OptionContext c) + { + action( + Parse(c.OptionValues[0], c), + Parse(c.OptionValues[1], c)); + } + } + + public OptionSet Add(string prototype, Action action) + { + return Add(prototype, null, action); + } + + public OptionSet Add(string prototype, string description, Action action) + { + return Add(new ActionOption(prototype, description, action)); + } + + public OptionSet Add(string prototype, OptionAction action) + { + return Add(prototype, null, action); + } + + public OptionSet Add(string prototype, string description, OptionAction action) + { + return Add(new ActionOption(prototype, description, action)); + } + + protected virtual OptionContext CreateOptionContext() + { + return new OptionContext(this); + } #if LINQ public List Parse (IEnumerable arguments) @@ -709,386 +740,427 @@ from argument in arguments return r; } #else - public List Parse (IEnumerable arguments) - { - OptionContext c = CreateOptionContext (); - c.OptionIndex = -1; - bool process = true; - List unprocessed = new List (); - Option def = Contains ("<>") ? this ["<>"] : null; - foreach (string argument in arguments) { - ++c.OptionIndex; - if (argument == "--") { - process = false; - continue; - } - if (!process) { - Unprocessed (unprocessed, def, c, argument); - continue; - } - if (!Parse (argument, c)) - Unprocessed (unprocessed, def, c, argument); - } - if (c.Option != null) - c.Option.Invoke (c); - return unprocessed; - } + public List Parse(IEnumerable arguments) + { + OptionContext c = CreateOptionContext(); + c.OptionIndex = -1; + bool process = true; + List unprocessed = new List(); + Option def = Contains("<>") ? this["<>"] : null; + foreach (string argument in arguments) + { + ++c.OptionIndex; + if (argument == "--") + { + process = false; + continue; + } + if (!process) + { + Unprocessed(unprocessed, def, c, argument); + continue; + } + if (!Parse(argument, c)) + Unprocessed(unprocessed, def, c, argument); + } + if (c.Option != null) + c.Option.Invoke(c); + return unprocessed; + } #endif - private static bool Unprocessed (ICollection extra, Option def, OptionContext c, string argument) - { - if (def == null) { - extra.Add (argument); - return false; - } - c.OptionValues.Add (argument); - c.Option = def; - c.Option.Invoke (c); - return false; - } - - private readonly Regex ValueOption = new Regex ( - @"^(?--|-|/)(?[^:=]+)((?[:=])(?.*))?$"); - - protected bool GetOptionParts (string argument, out string flag, out string name, out string sep, out string value) - { - if (argument == null) - throw new ArgumentNullException ("argument"); - - flag = name = sep = value = null; - Match m = ValueOption.Match (argument); - if (!m.Success) { - return false; - } - flag = m.Groups ["flag"].Value; - name = m.Groups ["name"].Value; - if (m.Groups ["sep"].Success && m.Groups ["value"].Success) { - sep = m.Groups ["sep"].Value; - value = m.Groups ["value"].Value; - } - return true; - } - - protected virtual bool Parse (string argument, OptionContext c) - { - if (c.Option != null) { - ParseValue (argument, c); - return true; - } - - string f, n, s, v; - if (!GetOptionParts (argument, out f, out n, out s, out v)) - return false; - - Option p; - if (Contains (n)) { - p = this [n]; - c.OptionName = f + n; - c.Option = p; - switch (p.OptionValueType) { - case OptionValueType.None: - c.OptionValues.Add (n); - c.Option.Invoke (c); - break; - case OptionValueType.Optional: - case OptionValueType.Required: - ParseValue (v, c); - break; - } - return true; - } - // no match; is it a bool option? - if (ParseBool (argument, n, c)) - return true; - // is it a bundled option? - if (ParseBundledValue (f, string.Concat (n + s + v), c)) - return true; - - return false; - } - - private void ParseValue (string option, OptionContext c) - { - if (option != null) - foreach (string o in c.Option.ValueSeparators != null - ? option.Split (c.Option.ValueSeparators, StringSplitOptions.None) - : new string[]{option}) { - c.OptionValues.Add (o); - } - if (c.OptionValues.Count == c.Option.MaxValueCount || - c.Option.OptionValueType == OptionValueType.Optional) - c.Option.Invoke (c); - else if (c.OptionValues.Count > c.Option.MaxValueCount) { - throw new OptionException (localizer (string.Format ( - "Error: Found {0} option values when expecting {1}.", - c.OptionValues.Count, c.Option.MaxValueCount)), - c.OptionName); - } - } - - private bool ParseBool (string option, string n, OptionContext c) - { - Option p; - string rn; - if (n.Length >= 1 && (n [n.Length-1] == '+' || n [n.Length-1] == '-') && - Contains ((rn = n.Substring (0, n.Length-1)))) { - p = this [rn]; - string v = n [n.Length-1] == '+' ? option : null; - c.OptionName = option; - c.Option = p; - c.OptionValues.Add (v); - p.Invoke (c); - return true; - } - return false; - } - - private bool ParseBundledValue (string f, string n, OptionContext c) - { - if (f != "-") - return false; - for (int i = 0; i < n.Length; ++i) { - Option p; - string opt = f + n [i].ToString (); - string rn = n [i].ToString (); - if (!Contains (rn)) { - if (i == 0) - return false; - throw new OptionException (string.Format (localizer ( - "Cannot bundle unregistered option '{0}'."), opt), opt); - } - p = this [rn]; - switch (p.OptionValueType) { - case OptionValueType.None: - Invoke (c, opt, n, p); - break; - case OptionValueType.Optional: - case OptionValueType.Required: { - string v = n.Substring (i+1); - c.Option = p; - c.OptionName = opt; - ParseValue (v.Length != 0 ? v : null, c); - return true; - } - default: - throw new InvalidOperationException ("Unknown OptionValueType: " + p.OptionValueType); - } - } - return true; - } - - private static void Invoke (OptionContext c, string name, string value, Option option) - { - c.OptionName = name; - c.Option = option; - c.OptionValues.Add (value); - option.Invoke (c); - } - - private const int OptionWidth = 29; - - public void WriteOptionDescriptions (TextWriter o) - { - foreach (Option p in this) { - int written = 0; - if (!WriteOptionPrototype (o, p, ref written)) - continue; - - if (written < OptionWidth) - o.Write (new string (' ', OptionWidth - written)); - else { - o.WriteLine (); - o.Write (new string (' ', OptionWidth)); - } - - List lines = GetLines (localizer (GetDescription (p.Description))); - o.WriteLine (lines [0]); - string prefix = new string (' ', OptionWidth+2); - for (int i = 1; i < lines.Count; ++i) { - o.Write (prefix); - o.WriteLine (lines [i]); - } - } - } - - bool WriteOptionPrototype (TextWriter o, Option p, ref int written) - { - string[] names = p.Names; - - int i = GetNextOptionIndex (names, 0); - if (i == names.Length) - return false; - - if (names [i].Length == 1) { - Write (o, ref written, " -"); - Write (o, ref written, names [0]); - } - else { - Write (o, ref written, " --"); - Write (o, ref written, names [0]); - } - - for ( i = GetNextOptionIndex (names, i+1); - i < names.Length; i = GetNextOptionIndex (names, i+1)) { - Write (o, ref written, ", "); - Write (o, ref written, names [i].Length == 1 ? "-" : "--"); - Write (o, ref written, names [i]); - } - - if (p.OptionValueType == OptionValueType.Optional || - p.OptionValueType == OptionValueType.Required) { - if (p.OptionValueType == OptionValueType.Optional) { - Write (o, ref written, localizer ("[")); - } - Write (o, ref written, localizer ("=" + GetArgumentName (0, p.MaxValueCount, p.Description))); - string sep = p.ValueSeparators != null && p.ValueSeparators.Length > 0 - ? p.ValueSeparators [0] - : " "; - for (int c = 1; c < p.MaxValueCount; ++c) { - Write (o, ref written, localizer (sep + GetArgumentName (c, p.MaxValueCount, p.Description))); - } - if (p.OptionValueType == OptionValueType.Optional) { - Write (o, ref written, localizer ("]")); - } - } - return true; - } - - static int GetNextOptionIndex (string[] names, int i) - { - while (i < names.Length && names [i] == "<>") { - ++i; - } - return i; - } - - static void Write (TextWriter o, ref int n, string s) - { - n += s.Length; - o.Write (s); - } - - private static string GetArgumentName (int index, int maxIndex, string description) - { - if (description == null) - return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1); - string[] nameStart; - if (maxIndex == 1) - nameStart = new string[]{"{0:", "{"}; - else - nameStart = new string[]{"{" + index + ":"}; - for (int i = 0; i < nameStart.Length; ++i) { - int start, j = 0; - do { - start = description.IndexOf (nameStart [i], j); - } while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false); - if (start == -1) - continue; - int end = description.IndexOf ("}", start); - if (end == -1) - continue; - return description.Substring (start + nameStart [i].Length, end - start - nameStart [i].Length); - } - return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1); - } - - private static string GetDescription (string description) - { - if (description == null) - return string.Empty; - StringBuilder sb = new StringBuilder (description.Length); - int start = -1; - for (int i = 0; i < description.Length; ++i) { - switch (description [i]) { - case '{': - if (i == start) { - sb.Append ('{'); - start = -1; - } - else if (start < 0) - start = i + 1; - break; - case '}': - if (start < 0) { - if ((i+1) == description.Length || description [i+1] != '}') - throw new InvalidOperationException ("Invalid option description: " + description); - ++i; - sb.Append ("}"); - } - else { - sb.Append (description.Substring (start, i - start)); - start = -1; - } - break; - case ':': - if (start < 0) - goto default; - start = i + 1; - break; - default: - if (start < 0) - sb.Append (description [i]); - break; - } - } - return sb.ToString (); - } - - private static List GetLines (string description) - { - List lines = new List (); - if (string.IsNullOrEmpty (description)) { - lines.Add (string.Empty); - return lines; - } - int length = 80 - OptionWidth - 2; - int start = 0, end; - do { - end = GetLineEnd (start, length, description); - bool cont = false; - if (end < description.Length) { - char c = description [end]; - if (c == '-' || (char.IsWhiteSpace (c) && c != '\n')) - ++end; - else if (c != '\n') { - cont = true; - --end; - } - } - lines.Add (description.Substring (start, end - start)); - if (cont) { - lines [lines.Count-1] += "-"; - } - start = end; - if (start < description.Length && description [start] == '\n') - ++start; - } while (end < description.Length); - return lines; - } - - private static int GetLineEnd (int start, int length, string description) - { - int end = Math.Min (start + length, description.Length); - int sep = -1; - for (int i = start; i < end; ++i) { - switch (description [i]) { - case ' ': - case '\t': - case '\v': - case '-': - case ',': - case '.': - case ';': - sep = i; - break; - case '\n': - return i; - } - } - if (sep == -1 || end == description.Length) - return end; - return sep; - } - } + private static bool Unprocessed(ICollection extra, Option def, OptionContext c, string argument) + { + if (def == null) + { + extra.Add(argument); + return false; + } + c.OptionValues.Add(argument); + c.Option = def; + c.Option.Invoke(c); + return false; + } + + private readonly Regex ValueOption = new Regex( + @"^(?--|-|/)(?[^:=]+)((?[:=])(?.*))?$"); + + protected bool GetOptionParts(string argument, out string flag, out string name, out string sep, out string value) + { + if (argument == null) + throw new ArgumentNullException("argument"); + + flag = name = sep = value = null; + Match m = ValueOption.Match(argument); + if (!m.Success) + { + return false; + } + flag = m.Groups["flag"].Value; + name = m.Groups["name"].Value; + if (m.Groups["sep"].Success && m.Groups["value"].Success) + { + sep = m.Groups["sep"].Value; + value = m.Groups["value"].Value; + } + return true; + } + + protected virtual bool Parse(string argument, OptionContext c) + { + if (c.Option != null) + { + ParseValue(argument, c); + return true; + } + + string f, n, s, v; + if (!GetOptionParts(argument, out f, out n, out s, out v)) + return false; + + Option p; + if (Contains(n)) + { + p = this[n]; + c.OptionName = f + n; + c.Option = p; + switch (p.OptionValueType) + { + case OptionValueType.None: + c.OptionValues.Add(n); + c.Option.Invoke(c); + break; + case OptionValueType.Optional: + case OptionValueType.Required: + ParseValue(v, c); + break; + } + return true; + } + // no match; is it a bool option? + if (ParseBool(argument, n, c)) + return true; + // is it a bundled option? + if (ParseBundledValue(f, string.Concat(n + s + v), c)) + return true; + + return false; + } + + private void ParseValue(string option, OptionContext c) + { + if (option != null) + foreach (string o in c.Option.ValueSeparators != null + ? option.Split(c.Option.ValueSeparators, StringSplitOptions.None) + : new string[] { option }) + { + c.OptionValues.Add(o); + } + if (c.OptionValues.Count == c.Option.MaxValueCount || + c.Option.OptionValueType == OptionValueType.Optional) + c.Option.Invoke(c); + else if (c.OptionValues.Count > c.Option.MaxValueCount) + { + throw new OptionException(localizer(string.Format( + "Error: Found {0} option values when expecting {1}.", + c.OptionValues.Count, c.Option.MaxValueCount)), + c.OptionName); + } + } + + private bool ParseBool(string option, string n, OptionContext c) + { + Option p; + string rn; + if (n.Length >= 1 && (n[n.Length - 1] == '+' || n[n.Length - 1] == '-') && + Contains((rn = n.Substring(0, n.Length - 1)))) + { + p = this[rn]; + string v = n[n.Length - 1] == '+' ? option : null; + c.OptionName = option; + c.Option = p; + c.OptionValues.Add(v); + p.Invoke(c); + return true; + } + return false; + } + + private bool ParseBundledValue(string f, string n, OptionContext c) + { + if (f != "-") + return false; + for (int i = 0; i < n.Length; ++i) + { + Option p; + string opt = f + n[i].ToString(); + string rn = n[i].ToString(); + if (!Contains(rn)) + { + if (i == 0) + return false; + throw new OptionException(string.Format(localizer( + "Cannot bundle unregistered option '{0}'."), opt), opt); + } + p = this[rn]; + switch (p.OptionValueType) + { + case OptionValueType.None: + Invoke(c, opt, n, p); + break; + case OptionValueType.Optional: + case OptionValueType.Required: + { + string v = n.Substring(i + 1); + c.Option = p; + c.OptionName = opt; + ParseValue(v.Length != 0 ? v : null, c); + return true; + } + default: + throw new InvalidOperationException("Unknown OptionValueType: " + p.OptionValueType); + } + } + return true; + } + + private static void Invoke(OptionContext c, string name, string value, Option option) + { + c.OptionName = name; + c.Option = option; + c.OptionValues.Add(value); + option.Invoke(c); + } + + private const int OptionWidth = 29; + + public void WriteOptionDescriptions(TextWriter o) + { + foreach (Option p in this) + { + int written = 0; + if (!WriteOptionPrototype(o, p, ref written)) + continue; + + if (written < OptionWidth) + o.Write(new string(' ', OptionWidth - written)); + else + { + o.WriteLine(); + o.Write(new string(' ', OptionWidth)); + } + + List lines = GetLines(localizer(GetDescription(p.Description))); + o.WriteLine(lines[0]); + string prefix = new string(' ', OptionWidth + 2); + for (int i = 1; i < lines.Count; ++i) + { + o.Write(prefix); + o.WriteLine(lines[i]); + } + } + } + + bool WriteOptionPrototype(TextWriter o, Option p, ref int written) + { + string[] names = p.Names; + + int i = GetNextOptionIndex(names, 0); + if (i == names.Length) + return false; + + if (names[i].Length == 1) + { + Write(o, ref written, " -"); + Write(o, ref written, names[0]); + } + else + { + Write(o, ref written, " --"); + Write(o, ref written, names[0]); + } + + for (i = GetNextOptionIndex(names, i + 1); + i < names.Length; i = GetNextOptionIndex(names, i + 1)) + { + Write(o, ref written, ", "); + Write(o, ref written, names[i].Length == 1 ? "-" : "--"); + Write(o, ref written, names[i]); + } + + if (p.OptionValueType == OptionValueType.Optional || + p.OptionValueType == OptionValueType.Required) + { + if (p.OptionValueType == OptionValueType.Optional) + { + Write(o, ref written, localizer("[")); + } + Write(o, ref written, localizer("=" + GetArgumentName(0, p.MaxValueCount, p.Description))); + string sep = p.ValueSeparators != null && p.ValueSeparators.Length > 0 + ? p.ValueSeparators[0] + : " "; + for (int c = 1; c < p.MaxValueCount; ++c) + { + Write(o, ref written, localizer(sep + GetArgumentName(c, p.MaxValueCount, p.Description))); + } + if (p.OptionValueType == OptionValueType.Optional) + { + Write(o, ref written, localizer("]")); + } + } + return true; + } + + static int GetNextOptionIndex(string[] names, int i) + { + while (i < names.Length && names[i] == "<>") + { + ++i; + } + return i; + } + + static void Write(TextWriter o, ref int n, string s) + { + n += s.Length; + o.Write(s); + } + + private static string GetArgumentName(int index, int maxIndex, string description) + { + if (description == null) + return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1); + string[] nameStart; + if (maxIndex == 1) + nameStart = new string[] { "{0:", "{" }; + else + nameStart = new string[] { "{" + index + ":" }; + for (int i = 0; i < nameStart.Length; ++i) + { + int start, j = 0; + do + { + start = description.IndexOf(nameStart[i], j); + } while (start >= 0 && j != 0 ? description[j++ - 1] == '{' : false); + if (start == -1) + continue; + int end = description.IndexOf("}", start); + if (end == -1) + continue; + return description.Substring(start + nameStart[i].Length, end - start - nameStart[i].Length); + } + return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1); + } + + private static string GetDescription(string description) + { + if (description == null) + return string.Empty; + StringBuilder sb = new StringBuilder(description.Length); + int start = -1; + for (int i = 0; i < description.Length; ++i) + { + switch (description[i]) + { + case '{': + if (i == start) + { + sb.Append('{'); + start = -1; + } + else if (start < 0) + start = i + 1; + break; + case '}': + if (start < 0) + { + if ((i + 1) == description.Length || description[i + 1] != '}') + throw new InvalidOperationException("Invalid option description: " + description); + ++i; + sb.Append("}"); + } + else + { + sb.Append(description.Substring(start, i - start)); + start = -1; + } + break; + case ':': + if (start < 0) + goto default; + start = i + 1; + break; + default: + if (start < 0) + sb.Append(description[i]); + break; + } + } + return sb.ToString(); + } + + private static List GetLines(string description) + { + List lines = new List(); + if (string.IsNullOrEmpty(description)) + { + lines.Add(string.Empty); + return lines; + } + int length = 80 - OptionWidth - 2; + int start = 0, end; + do + { + end = GetLineEnd(start, length, description); + bool cont = false; + if (end < description.Length) + { + char c = description[end]; + if (c == '-' || (char.IsWhiteSpace(c) && c != '\n')) + ++end; + else if (c != '\n') + { + cont = true; + --end; + } + } + lines.Add(description.Substring(start, end - start)); + if (cont) + { + lines[lines.Count - 1] += "-"; + } + start = end; + if (start < description.Length && description[start] == '\n') + ++start; + } while (end < description.Length); + return lines; + } + + private static int GetLineEnd(int start, int length, string description) + { + int end = Math.Min(start + length, description.Length); + int sep = -1; + for (int i = start; i < end; ++i) + { + switch (description[i]) + { + case ' ': + case '\t': + case '\v': + case '-': + case ',': + case '.': + case ';': + sep = i; + break; + case '\n': + return i; + } + } + if (sep == -1 || end == description.Length) + return end; + return sep; + } + } } diff --git a/Humpback/ConfigurationOptions/Project.cs b/Humpback/ConfigurationOptions/Project.cs index a67b579..a6c75ed 100644 --- a/Humpback/ConfigurationOptions/Project.cs +++ b/Humpback/ConfigurationOptions/Project.cs @@ -1,10 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Humpback.ConfigurationOptions { - public class Project { +namespace Humpback.ConfigurationOptions +{ + public class Project + { public string name { get; set; } public string directory { get; set; } public string connection_string { get; set; } diff --git a/Humpback/ConfigurationOptions/Settings.cs b/Humpback/ConfigurationOptions/Settings.cs index 79a9d50..06dbea1 100644 --- a/Humpback/ConfigurationOptions/Settings.cs +++ b/Humpback/ConfigurationOptions/Settings.cs @@ -6,23 +6,29 @@ using System.Text; using System.Web.Script.Serialization; -namespace Humpback.ConfigurationOptions { - public class Settings { +namespace Humpback.ConfigurationOptions +{ + public class Settings + { public string CurrentProject { get; set; } public Project[] Projects { get; set; } - public Settings() { + public Settings() + { Projects = new Project[0]; } - public Settings(string project_name, Project[] projects) { + public Settings(string project_name, Project[] projects) + { Projects = projects; CurrentProject = project_name; } - public static Settings Load() { - if (!File.Exists(SettingsFilePath)) { + public static Settings Load() + { + if (!File.Exists(SettingsFilePath)) + { var settings = create("default"); settings.save(); return settings; @@ -32,43 +38,53 @@ public static Settings Load() { return (Settings)serializer.Deserialize(json, typeof(Settings)); } - public Project SetCurrent(string project_name) { + public Project SetCurrent(string project_name) + { validate_current_project(project_name); CurrentProject = project_name.ToLower(); save(); return GetCurrent(); } - public Project GetCurrent() { + public Project GetCurrent() + { validate_current_project(CurrentProject); return Projects.Single(p => p.name == CurrentProject); } - public string SqlFileFolder() { + public string SqlFileFolder() + { var i = new DirectoryInfo(GetCurrent().directory); return Path.Combine(i.FullName, "sql"); } - public string MigrationsFolder() { + public string MigrationsFolder() + { var i = new DirectoryInfo(GetCurrent().directory); return Path.Combine(i.FullName, "migrations"); } - public string OutputFolder() { + public string OutputFolder() + { var i = new DirectoryInfo(GetCurrent().directory); return Path.Combine(i.FullName, "generated"); } - public string ConnectionString() { + public string ConnectionString() + { return GetCurrent().connection_string; } - public void Rename(string new_name) { - if (string.IsNullOrWhiteSpace(new_name)) { + public void Rename(string new_name) + { + if (string.IsNullOrWhiteSpace(new_name)) + { throw new InvalidDataException("please specify a name with some printable characters."); } - foreach(var proj in Projects) { - if(proj.name == CurrentProject) { + foreach (var proj in Projects) + { + if (proj.name == CurrentProject) + { proj.name = new_name.ToLower(); CurrentProject = new_name.ToLower(); break; @@ -77,45 +93,57 @@ public void Rename(string new_name) { save(); } - public void SetDirectory(string new_directory) { - if (string.IsNullOrWhiteSpace(new_directory)) { + public void SetDirectory(string new_directory) + { + if (string.IsNullOrWhiteSpace(new_directory)) + { throw new InvalidDataException("please specify a directory path with some printable characters."); } - if (!Directory.Exists(new_directory)) { + if (!Directory.Exists(new_directory)) + { Directory.CreateDirectory(new_directory); } GetCurrent().directory = new_directory; save(); } - public void SetConnectionString(string new_connection_string) { - if (string.IsNullOrWhiteSpace(new_connection_string)) { + public void SetConnectionString(string new_connection_string) + { + if (string.IsNullOrWhiteSpace(new_connection_string)) + { throw new InvalidDataException("please specify a connection string with some printable characters."); } GetCurrent().connection_string = new_connection_string; save(); } - internal void SetFlavor(string new_flavor) { - if (string.IsNullOrWhiteSpace(new_flavor)) { + internal void SetFlavor(string new_flavor) + { + if (string.IsNullOrWhiteSpace(new_flavor)) + { throw new InvalidDataException("please specify a flavor with some printable characters."); } var flavors = new HashSet { "sqlserver" }; - if (!flavors.Contains(new_flavor.ToLower())) { + if (!flavors.Contains(new_flavor.ToLower())) + { throw new InvalidDataException("currently sqlserver is the only flavor."); } GetCurrent().flavor = new_flavor.ToLower(); save(); } - internal void AddProject(string project_name) { - if (string.IsNullOrWhiteSpace(project_name)) { + internal void AddProject(string project_name) + { + if (string.IsNullOrWhiteSpace(project_name)) + { throw new InvalidOperationException("No current project specified."); } - if (Projects.Any(p => p.name == project_name)) { + if (Projects.Any(p => p.name == project_name)) + { throw new InvalidDataException(string.Format("'{0}' is already a project.", project_name)); } - var project = new Project { + var project = new Project + { name = project_name.ToLower(), connection_string = "server=.;database=northwind;Integrated Security=True;", directory = Path.Combine(Environment.CurrentDirectory, "db"), @@ -127,44 +155,55 @@ internal void AddProject(string project_name) { save(); } - internal void Remove(string project_name) { + internal void Remove(string project_name) + { Projects = Projects.Where(p => p.name != project_name.ToLower()).ToArray(); - if(CurrentProject == project_name.ToLower()) { + if (CurrentProject == project_name.ToLower()) + { CurrentProject = ""; - if(Projects.Length > 0) { + if (Projects.Length > 0) + { CurrentProject = Projects.First().name; } } save(); } - private static Settings create(string project_name) { - var project = new Project { + private static Settings create(string project_name) + { + var project = new Project + { name = project_name.ToLower(), connection_string = "server=.;database=northwind;Integrated Security=True;", directory = Path.Combine(Environment.CurrentDirectory, "db"), flavor = "sqlserver" }; - return new Settings { + return new Settings + { CurrentProject = project_name.ToLower(), Projects = new[] { project } }; } - private void validate_current_project(string project) { - if (string.IsNullOrWhiteSpace(project)) { + private void validate_current_project(string project) + { + if (string.IsNullOrWhiteSpace(project)) + { throw new InvalidOperationException("No current project set."); } - if (!Projects.Any(p => p.name == project)) { + if (!Projects.Any(p => p.name == project)) + { throw new KeyNotFoundException(string.Format("'{0}' is not a valid project.", project)); } } - private void save() { + private void save() + { var file_path = SettingsFilePath; var fi = new FileInfo(file_path); - if (!fi.Directory.Exists) { + if (!fi.Directory.Exists) + { Directory.CreateDirectory(fi.Directory.FullName); } @@ -174,36 +213,45 @@ private void save() { EnsureDirectories(); } - internal void EnsureDirectories() { - if (!Directory.Exists(MigrationsFolder())) { + internal void EnsureDirectories() + { + if (!Directory.Exists(MigrationsFolder())) + { Directory.CreateDirectory(MigrationsFolder()); } - if (!Directory.Exists(OutputFolder())) { + if (!Directory.Exists(OutputFolder())) + { Directory.CreateDirectory(OutputFolder()); } - if (!Directory.Exists(SqlFileFolder())) { + if (!Directory.Exists(SqlFileFolder())) + { Directory.CreateDirectory(SqlFileFolder()); } } - internal static string SettingsFilePath { - get { + internal static string SettingsFilePath + { + get + { // if local exists, use it, otherwise return the Application Settings Version return local_settings_file_if_exists() ?? application_settings_file_path(); } } - private static string application_settings_file_path() { + private static string application_settings_file_path() + { var app_data_path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); var app_settings_path = Path.Combine(app_data_path, "humpback"); var app_settings_file_path = Path.Combine(app_settings_path, "settings.js"); return app_settings_file_path; } - private static string local_settings_file_if_exists() { + private static string local_settings_file_if_exists() + { var current_path = new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName; var local_file_path = Path.Combine(current_path, "settings.js"); - if (File.Exists(local_file_path)) { + if (File.Exists(local_file_path)) + { return local_file_path; } return null; diff --git a/Humpback/Humpback.csproj b/Humpback/Humpback.csproj index 4ca6125..a619fe5 100644 --- a/Humpback/Humpback.csproj +++ b/Humpback/Humpback.csproj @@ -1,20 +1,36 @@  - + + Debug - x86 - 8.0.30703 - 2.0 - {2EA42E6C-D69E-46DD-AA57-5BDC47B1AFF3} + AnyCPU + {E7FEAF88-D6C7-4804-9950-E5F21C1D5811} Exe - Properties Humpback Hump - v4.0 + v4.7.2 512 - + true + true + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + - + AnyCPU true full @@ -24,7 +40,7 @@ prompt 4 - + AnyCPU pdbonly true @@ -34,59 +50,228 @@ 4 - + + ..\packages\Azure.Core.1.44.1\lib\net472\Azure.Core.dll + + + ..\packages\Azure.Identity.1.13.1\lib\netstandard2.0\Azure.Identity.dll + + + ..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll + + + ..\packages\Microsoft.Bcl.AsyncInterfaces.9.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Bcl.TimeProvider.9.0.0\lib\net462\Microsoft.Bcl.TimeProvider.dll + + + ..\packages\Microsoft.Data.SqlClient.5.2.2\lib\net462\Microsoft.Data.SqlClient.dll + + + ..\packages\Microsoft.Identity.Client.4.66.2\lib\net472\Microsoft.Identity.Client.dll + + + ..\packages\Microsoft.Identity.Client.Extensions.Msal.4.66.2\lib\netstandard2.0\Microsoft.Identity.Client.Extensions.Msal.dll + + + ..\packages\Microsoft.IdentityModel.Abstractions.8.2.1\lib\net472\Microsoft.IdentityModel.Abstractions.dll + + + ..\packages\Microsoft.IdentityModel.JsonWebTokens.8.2.1\lib\net472\Microsoft.IdentityModel.JsonWebTokens.dll + + + ..\packages\Microsoft.IdentityModel.Logging.8.2.1\lib\net472\Microsoft.IdentityModel.Logging.dll + + + ..\packages\Microsoft.IdentityModel.Protocols.8.2.1\lib\net472\Microsoft.IdentityModel.Protocols.dll + + + ..\packages\Microsoft.IdentityModel.Protocols.OpenIdConnect.8.2.1\lib\net472\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll + + + ..\packages\Microsoft.IdentityModel.Tokens.8.2.1\lib\net472\Microsoft.IdentityModel.Tokens.dll + - + + ..\packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll + + + ..\packages\System.ClientModel.1.2.1\lib\netstandard2.0\System.ClientModel.dll + + + + + ..\packages\System.Configuration.ConfigurationManager.9.0.0\lib\net462\System.Configuration.ConfigurationManager.dll + - + + + ..\packages\System.Diagnostics.DiagnosticSource.9.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll + + + + + + ..\packages\System.IdentityModel.Tokens.Jwt.8.2.1\lib\net472\System.IdentityModel.Tokens.Jwt.dll + + + ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll + True + True + + + ..\packages\System.IO.FileSystem.AccessControl.5.0.0\lib\net461\System.IO.FileSystem.AccessControl.dll + + + ..\packages\System.IO.Pipelines.9.0.0\lib\net462\System.IO.Pipelines.dll + + + ..\packages\System.Memory.4.6.0\lib\net462\System.Memory.dll + + + ..\packages\System.Memory.Data.9.0.0\lib\net462\System.Memory.Data.dll + + + + ..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll + True + True + + + + ..\packages\System.Numerics.Vectors.4.6.0\lib\net462\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll + True + True + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.1.0\lib\net462\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + + + + ..\packages\System.Security.AccessControl.6.0.1\lib\net461\System.Security.AccessControl.dll + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll + True + True + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + ..\packages\System.Security.Cryptography.ProtectedData.9.0.0\lib\net462\System.Security.Cryptography.ProtectedData.dll + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + + + ..\packages\System.Security.Permissions.9.0.0\lib\net462\System.Security.Permissions.dll + + + ..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + + + + ..\packages\System.Text.Encodings.Web.9.0.0\lib\net462\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.9.0.0\lib\net462\System.Text.Json.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.6.0\lib\net462\System.Threading.Tasks.Extensions.dll + + + + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + + + + + + Properties\SharedVersionInfo.cs + + - - - - + - + + + + - + + + + - {B830E3E4-3942-48BB-97A8-3E9BB0E9F1E1} + {15eadec7-be27-4334-ba95-0ff3f6bd8a78} Humpback.Interfaces + + {804678ae-b193-4a4e-ade7-b02b66361f73} + Humpback.Smo + - + + False + Microsoft .NET Framework 4.7.2 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + - - + - \ No newline at end of file diff --git a/Humpback/IHumpbackCommand.cs b/Humpback/IHumpbackCommand.cs index 54e394b..2fab437 100644 --- a/Humpback/IHumpbackCommand.cs +++ b/Humpback/IHumpbackCommand.cs @@ -1,10 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Humpback { - public interface IHumpbackCommand { +namespace Humpback +{ + public interface IHumpbackCommand + { void Execute(); } } diff --git a/Humpback/ILLink/ILLink.Descriptors.LibraryBuild.xml b/Humpback/ILLink/ILLink.Descriptors.LibraryBuild.xml new file mode 100644 index 0000000..a42d7f0 --- /dev/null +++ b/Humpback/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Humpback/Parts/FileWriter.cs b/Humpback/Parts/FileWriter.cs index 3742c38..664a3b5 100644 --- a/Humpback/Parts/FileWriter.cs +++ b/Humpback/Parts/FileWriter.cs @@ -1,13 +1,17 @@ -using System.Text; -using Humpback.Interfaces; +using Humpback.Interfaces; +using System.Text; -namespace Humpback { - class FileWriter : IFileWriter { - public void WriteFile(string path, string contents) { +namespace Humpback +{ + class FileWriter : IFileWriter + { + public void WriteFile(string path, string contents) + { System.IO.File.WriteAllText(path, contents, Encoding.UTF8); } - public bool FileExists(string path) { + public bool FileExists(string path) + { return System.IO.File.Exists(path); } } diff --git a/Humpback/Parts/GenerateSQL.cs b/Humpback/Parts/GenerateSQL.cs index ffe62a9..434a2c7 100644 --- a/Humpback/Parts/GenerateSQL.cs +++ b/Humpback/Parts/GenerateSQL.cs @@ -1,13 +1,15 @@ -using System; +using Humpback.ConfigurationOptions; +using Humpback.Interfaces; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using Humpback.ConfigurationOptions; -using Humpback.Interfaces; -namespace Humpback.Parts { - public class GenerateSQL : IHumpbackCommand { +namespace Humpback.Parts +{ + public class GenerateSQL : IHumpbackCommand + { private ISqlFormatter _sql_formatter; private IFileWriter _file_writer; @@ -15,7 +17,8 @@ public class GenerateSQL : IHumpbackCommand { private IMigrationProvider _migration_provider; private Settings _settings; - public GenerateSQL(Configuration configuration, Settings settings, ISqlFormatter sql_formatter, IFileWriter file_writer, IMigrationProvider migration_provider) { + public GenerateSQL(Configuration configuration, Settings settings, ISqlFormatter sql_formatter, IFileWriter file_writer, IMigrationProvider migration_provider) + { _configuration = configuration; _settings = settings; _sql_formatter = sql_formatter; @@ -33,79 +36,106 @@ public GenerateSQL(Configuration configuration, Settings settings, ISqlFormatter // generate sql file for all migrations not deployed hump -s -ndp -single - public void Execute() { - if(_configuration.All) { + public void Execute() + { + if (_configuration.All) + { SaveAllSql(); - } else if (_configuration.Deployed) { + } + else if (_configuration.Deployed) + { SaveDeployed(); - } else if (_configuration.NotDeployed) { + } + else if (_configuration.NotDeployed) + { SaveUnDeployed(); - } else if (SingleMigrationID() > 0) { + } + else if (SingleMigrationID() > 0) + { SaveSingle(SingleMigrationID()); - } else { + } + else + { SaveAllSql(); } } - private void SaveSingle(int migration_id) { + private void SaveSingle(int migration_id) + { var migrations = _migration_provider.GetMigrations(); var migration_contents = _migration_provider.GetMigrationsContents(); CreateSql(migrations, migration_contents, v => v.Key == migration_id); } - private void SaveUnDeployed() { + private void SaveUnDeployed() + { var migrations = _migration_provider.GetMigrations(); var migration_contents = _migration_provider.GetMigrationsContents(); CreateSql(migrations, migration_contents, v => v.Key > _migration_provider.DatabaseMigrationNumber()); } - private void SaveDeployed() { + private void SaveDeployed() + { var migrations = _migration_provider.GetMigrations(); var migration_contents = _migration_provider.GetMigrationsContents(); - CreateSql(migrations, migration_contents,v => v.Key <= _migration_provider.DatabaseMigrationNumber()); + CreateSql(migrations, migration_contents, v => v.Key <= _migration_provider.DatabaseMigrationNumber()); } - private void SaveAllSql() { + private void SaveAllSql() + { var migrations = _migration_provider.GetMigrations(); var migration_contents = _migration_provider.GetMigrationsContents(); CreateSql(migrations, migration_contents, null); } - private void CreateSql(SortedDictionary migrations, SortedDictionary migration_contents, Predicate> allow_migration_func) { + private void CreateSql(SortedDictionary migrations, SortedDictionary migration_contents, Predicate> allow_migration_func) + { var sql_commands = new Dictionary(); int min = migrations.Count; int max = 1; - foreach(var migration in migrations) { - if(allow_migration_func != null) { - if(!allow_migration_func(migration)) { + foreach (var migration in migrations) + { + if (allow_migration_func != null) + { + if (!allow_migration_func(migration)) + { continue; } } - if(migration.Key < min) { + if (migration.Key < min) + { min = migration.Key; } - if(migration.Key > max) { + if (migration.Key > max) + { max = migration.Key; } var this_migration_contents = migration_contents[migration.Key]; dynamic migration_object = Helpers.DeserializeMigration(this_migration_contents); var commands = _sql_formatter.GenerateSQLUp(migration_object); - if(commands.Length == 1 ) { + if (commands.Length == 1) + { sql_commands.Add(_sql_formatter.sql_file_name(migration.Value), commands[0]); - } else { - for (int i = 0; i < commands.Length; i++) { - sql_commands.Add(_sql_formatter.sql_file_name(migration.Value) + "." + (i+1).ToString("000"), commands[i]); + } + else + { + for (int i = 0; i < commands.Length; i++) + { + sql_commands.Add(_sql_formatter.sql_file_name(migration.Value) + "." + (i + 1).ToString("000"), commands[i]); } } - + } - WriteFile(sql_commands,min,max); + WriteFile(sql_commands, min, max); } - private void WriteFile(Dictionary sql_commands, int from, int to) { - if(_configuration.Single) { + private void WriteFile(Dictionary sql_commands, int from, int to) + { + if (_configuration.Single) + { var sb = new StringBuilder(); sb.AppendLine(); sb.AppendLine().AppendLine("-- BEGIN TRANSACTION"); sb.AppendLine(); - foreach(var cmd in sql_commands.Values) { + foreach (var cmd in sql_commands.Values) + { sb.AppendLine().AppendLine(cmd).AppendLine().AppendLine("GO").AppendLine(); } string file_name = string.Format("{0}_ALL_SQL_Migrations_{1}_thru_{2}.sql", @@ -117,8 +147,11 @@ private void WriteFile(Dictionary sql_commands, int from, int to) sb.AppendLine().AppendLine().AppendLine(); WriteOutput(sb.ToString(), file_name); - } else { - foreach (var cmd in sql_commands) { + } + else + { + foreach (var cmd in sql_commands) + { string file_name = _sql_formatter.sql_file_name(cmd.Key); string sql_out = string.Format("{0}{0}{1}{0}{0}{0}", Environment.NewLine, cmd.Value); WriteOutput(sql_out, file_name); @@ -126,11 +159,16 @@ private void WriteFile(Dictionary sql_commands, int from, int to) } } - private void WriteOutput(string sql_out, string file_name) { - if (_configuration.Screen) { + private void WriteOutput(string sql_out, string file_name) + { + if (_configuration.Screen) + { Console.WriteLine(sql_out); - } else { - if(file_name.Contains("\\")){ + } + else + { + if (file_name.Contains("\\")) + { file_name = new FileInfo(file_name).Name; } _file_writer.WriteFile(Path.Combine(_settings.OutputFolder(), file_name), sql_out); @@ -138,7 +176,8 @@ private void WriteOutput(string sql_out, string file_name) { } - private int SingleMigrationID() { + private int SingleMigrationID() + { int migration_id = 0; bool has_extra = _configuration.Extra.Any(); bool extra_is_int = has_extra && int.TryParse(_configuration.Extra.First(), out migration_id); diff --git a/Humpback/Parts/Generator.cs b/Humpback/Parts/Generator.cs index 21868d4..eaf1d4a 100644 --- a/Humpback/Parts/Generator.cs +++ b/Humpback/Parts/Generator.cs @@ -1,24 +1,24 @@ -using System; -using System.Collections; +using Humpback.ConfigurationOptions; +using Humpback.Interfaces; +using System; using System.Collections.Generic; -using System.Dynamic; using System.IO; using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using System.Web.Script.Serialization; -using Humpback.ConfigurationOptions; -using Humpback.Interfaces; -namespace Humpback.Parts { - public class Generator : IHumpbackCommand { +namespace Humpback.Parts +{ + public class Generator : IHumpbackCommand + { private readonly Configuration _configuration; private readonly IFileWriter _file_writer; private Settings _settings; - public Generator(Configuration configuration, Settings settings, IFileWriter file_writer) { - if(!configuration.Generate) { + public Generator(Configuration configuration, Settings settings, IFileWriter file_writer) + { + if (!configuration.Generate) + { throw new InvalidOperationException("Configuration not correctly set for Generator"); } _file_writer = file_writer; @@ -28,54 +28,79 @@ public Generator(Configuration configuration, Settings settings, IFileWriter fil } - void set_generation_action() { + void set_generation_action() + { var generate_string = _configuration.GenerateString; var generate_string_upper = generate_string.ToUpperInvariant(); var ignore_case = StringComparison.InvariantCultureIgnoreCase; // sorry this was just big and ugly repeated below - if (generate_string.Equals("SQL", ignore_case)) { + if (generate_string.Equals("SQL", ignore_case)) + { GenerateAction = GenerateActionType.Sql; - } else if (generate_string.Equals("FILE", ignore_case)) { + } + else if (generate_string.Equals("FILE", ignore_case)) + { GenerateAction = GenerateActionType.File; - } else if (generate_string.Equals("SMO", ignore_case) || generate_string.Equals("FILESMO", ignore_case)) { + } + else if (generate_string.Equals("SMO", ignore_case) || generate_string.Equals("FILESMO", ignore_case)) + { GenerateAction = GenerateActionType.FileSmo; - } else if (generate_string_upper.StartsWith("ADD")) { + } + else if (generate_string_upper.StartsWith("ADD")) + { // check for keywords - if (generate_string_upper.StartsWith("ADDINDEXTO")) { + if (generate_string_upper.StartsWith("ADDINDEXTO")) + { GenerateAction = GenerateActionType.AddIndex; - } else { + } + else + { GenerateAction = GenerateActionType.AddColumn; } - } else if (generate_string_upper.StartsWith("REMOVE")) { + } + else if (generate_string_upper.StartsWith("REMOVE")) + { // check for keywords - if (generate_string_upper.StartsWith("REMOVEINDEXFROM")) { + if (generate_string_upper.StartsWith("REMOVEINDEXFROM")) + { GenerateAction = GenerateActionType.RemoveIndex; - } else { + } + else + { GenerateAction = GenerateActionType.RemoveColumn; } - } else if (generate_string_upper.StartsWith("DROP")) { + } + else if (generate_string_upper.StartsWith("DROP")) + { GenerateAction = GenerateActionType.RemoveTable; - } else if (generate_string_upper.StartsWith("CHANGE")) { + } + else if (generate_string_upper.StartsWith("CHANGE")) + { GenerateAction = GenerateActionType.ChangeColumn; - } else { + } + else + { GenerateAction = GenerateActionType.AddTable; } } - public GenerateActionType GenerateAction { + public GenerateActionType GenerateAction + { get; private set; } - public void Execute() { - switch (GenerateAction) { + public void Execute() + { + switch (GenerateAction) + { case GenerateActionType.AddTable: AddTable(); break; @@ -109,31 +134,38 @@ public void Execute() { } } - private void ChangeColumn() { + private void ChangeColumn() + { var nullables = new Dictionary(); var defaults = new Dictionary(); - var column_dictionary = GenerateColumns(nullables,defaults); + var column_dictionary = GenerateColumns(nullables, defaults); IList columns = new List(); - foreach (var column in column_dictionary) { - if (nullables.ContainsKey(column.Key) && defaults.ContainsKey(column.Key)) { + foreach (var column in column_dictionary) + { + if (nullables.ContainsKey(column.Key) && defaults.ContainsKey(column.Key)) + { columns.Add(new { name = column.Key, @type = column.Value, nullable = nullables[column.Key], @default = defaults[column.Key] }); - } - - else if(nullables.ContainsKey(column.Key)) { + } + + else if (nullables.ContainsKey(column.Key)) + { columns.Add(new { name = column.Key, @type = column.Value, nullable = nullables[column.Key] }); - } - else if (defaults.ContainsKey(column.Key)) { + } + else if (defaults.ContainsKey(column.Key)) + { columns.Add(new { name = column.Key, @type = column.Value, @default = defaults[column.Key] }); } - else { - columns.Add(new {name = column.Key, @type = column.Value}); + else + { + columns.Add(new { name = column.Key, @type = column.Value }); } - + } - if (!columns.Any()) { + if (!columns.Any()) + { columns.Add(new { name = "column_name_here", @type = "string" }); } @@ -147,17 +179,19 @@ private void ChangeColumn() { } - private string CreateFile(string action, dynamic obj) { + private string CreateFile(string action, dynamic obj) + { string serialized = Helpers.Json(obj); action = action.Replace(" ", "_"); - action = Regex.Replace(action, @"[^\w\-_]", ""); - string file_name = string.Format("{0}_{1}.js",_configuration.NextSerialNumber(),action); + action = Regex.Replace(action, @"[^\w\-_]", ""); + string file_name = string.Format("{0}_{1}.js", _configuration.NextSerialNumber(), action); var path = Path.Combine(_settings.MigrationsFolder(), file_name); _file_writer.WriteFile(path, serialized); return path; } - public void AddTable() { + public void AddTable() + { var nullables = new Dictionary(); @@ -166,32 +200,42 @@ public void AddTable() { IList columns = new List(); - foreach (var column in column_dictionary) { - if (nullables.ContainsKey(column.Key) && defaults.ContainsKey(column.Key)) { + foreach (var column in column_dictionary) + { + if (nullables.ContainsKey(column.Key) && defaults.ContainsKey(column.Key)) + { columns.Add(new { name = column.Key, @type = column.Value, nullable = nullables[column.Key], @default = defaults[column.Key] }); - } else if (nullables.ContainsKey(column.Key)) { + } + else if (nullables.ContainsKey(column.Key)) + { columns.Add(new { name = column.Key, @type = column.Value, nullable = nullables[column.Key] }); - } else if (defaults.ContainsKey(column.Key)) { + } + else if (defaults.ContainsKey(column.Key)) + { columns.Add(new { name = column.Key, @type = column.Value, @default = defaults[column.Key] }); - } else { + } + else + { columns.Add(new { name = column.Key, @type = column.Value }); } } var name = _configuration.GenerateString; - dynamic up = new {create_table=new{name,full_audit=true,columns}}; - dynamic down = new {drop_table=name}; - dynamic output_object = new {up, down}; + dynamic up = new { create_table = new { name, full_audit = true, columns } }; + dynamic down = new { drop_table = name }; + dynamic output_object = new { up, down }; CreateFile("AddTable_" + name, output_object); Console.WriteLine("Generating Migration " + "AddTable_" + name); Console.WriteLine(Helpers.Json(output_object)); } - public void RemoveTable() { + public void RemoveTable() + { var table_name = _configuration.GenerateString; - if(table_name.ToUpperInvariant().StartsWith("DROP")) { + if (table_name.ToUpperInvariant().StartsWith("DROP")) + { table_name = table_name.Substring(4); } dynamic up = new { drop_table = table_name }; @@ -202,17 +246,21 @@ public void RemoveTable() { } - public void AddColumn() { + public void AddColumn() + { string table_name = ""; string generate_string_upper = _configuration.GenerateString.ToUpperInvariant(); int esc_to_count = Regex.Matches(generate_string_upper, "_TO_").Count; int to_count = Regex.Matches(generate_string_upper, "TO").Count; string column_name = ""; - if (esc_to_count == 1) { + if (esc_to_count == 1) + { int ix = generate_string_upper.IndexOf("_TO_"); // TODO: substring matching issue: could be an issue here when this sequence is in the tablename, could go from end, but then column name has same issue. table_name = _configuration.GenerateString.Substring(ix + 4); column_name = _configuration.GenerateString.Substring(3, ix - 3); - } else if (to_count > 1) { + } + else if (to_count > 1) + { Console.WriteLine("Humpback is trying to help you."); Console.WriteLine( "You Are attempting to add a column to a table, but the letters 'TO' occur in the column name or the table name"); @@ -221,7 +269,9 @@ public void AddColumn() { Console.WriteLine("For instance AddCustomerName_TO_Orders"); Console.WriteLine("Migration NOT Created"); return; - } else if (generate_string_upper.StartsWith("ADD") && generate_string_upper.Contains("TO")) { + } + else if (generate_string_upper.StartsWith("ADD") && generate_string_upper.Contains("TO")) + { int ix = generate_string_upper.IndexOf("TO"); table_name = _configuration.GenerateString.Substring(ix + 2); column_name = _configuration.GenerateString.Substring(3, ix - 3); @@ -234,30 +284,43 @@ public void AddColumn() { IList columns = new List(); - foreach (var column in column_dictionary) { - if (nullables.ContainsKey(column.Key) && defaults.ContainsKey(column.Key)) { + foreach (var column in column_dictionary) + { + if (nullables.ContainsKey(column.Key) && defaults.ContainsKey(column.Key)) + { columns.Add(new { name = column.Key, @type = column.Value, nullable = nullables[column.Key], @default = defaults[column.Key] }); - } else if (nullables.ContainsKey(column.Key)) { + } + else if (nullables.ContainsKey(column.Key)) + { columns.Add(new { name = column.Key, @type = column.Value, nullable = nullables[column.Key] }); - } else if (defaults.ContainsKey(column.Key)) { + } + else if (defaults.ContainsKey(column.Key)) + { columns.Add(new { name = column.Key, @type = column.Value, @default = defaults[column.Key] }); - } else { + } + else + { columns.Add(new { name = column.Key, @type = column.Value }); } } - if(!columns.Any()) { - if (generate_string_upper.StartsWith("ADD") && generate_string_upper.Contains("TO")) { + if (!columns.Any()) + { + if (generate_string_upper.StartsWith("ADD") && generate_string_upper.Contains("TO")) + { string s = _configuration.GenerateString.Substring(3); int ix = s.ToUpperInvariant().IndexOf("TO"); columns.Add(new { name = column_name, @type = "string" }); - } else { - columns.Add(new {name = "add_column_name_here", @type = "string"}); + } + else + { + columns.Add(new { name = "add_column_name_here", @type = "string" }); } } string drop_col_name = columns.First().name; - if(columns.First().type == "reference") { + if (columns.First().type == "reference") + { drop_col_name += "Id"; } var table = table_name; // used for auto property naming in anon object below @@ -269,11 +332,13 @@ public void AddColumn() { Console.WriteLine(Helpers.Json(output_object)); } - public void RemoveColumn() { + public void RemoveColumn() + { string table_name = ""; string column_name = ""; if (_configuration.GenerateString.ToUpperInvariant().StartsWith("REMOVE") - && _configuration.GenerateString.ToUpperInvariant().Contains("FROM")) { + && _configuration.GenerateString.ToUpperInvariant().Contains("FROM")) + { string s = _configuration.GenerateString.Substring(6); int ix = s.ToUpperInvariant().IndexOf("FROM"); column_name = s.Substring(0, ix); @@ -288,34 +353,40 @@ public void RemoveColumn() { Console.WriteLine(Helpers.Json(output_object)); } - public void AddIndex() { + public void AddIndex() + { string table_name = ""; if (_configuration.GenerateString.ToUpperInvariant().StartsWith("ADDINDEXTO") - && _configuration.GenerateString.Length > 10) { - table_name = _configuration.GenerateString.Substring(10); + && _configuration.GenerateString.Length > 10) + { + table_name = _configuration.GenerateString.Substring(10); } var column_dictionary = GenerateColumns(); IList columns = column_dictionary.Select(column => column.Key).ToList(); - if (!columns.Any()) { + if (!columns.Any()) + { columns.Add("column_name_here"); } dynamic up = new { add_index = new { table_name, columns } }; dynamic output_object = new { up }; - CreateFile("AddIndex_" + table_name + "_" + String.Join("_",columns), output_object); + CreateFile("AddIndex_" + table_name + "_" + String.Join("_", columns), output_object); Console.WriteLine("Generating Migration " + "AddIndex_" + table_name + "_" + String.Join("_", columns)); Console.WriteLine(Helpers.Json(output_object)); } - public void RemoveIndex() { + public void RemoveIndex() + { string table_name = ""; string generate_string_upper = _configuration.GenerateString.ToUpperInvariant(); - if (generate_string_upper.StartsWith("REMOVEINDEXFROM") && generate_string_upper.Length > 15) { + if (generate_string_upper.StartsWith("REMOVEINDEXFROM") && generate_string_upper.Length > 15) + { table_name = _configuration.GenerateString.Substring(15); } Dictionary column_dictionary = GenerateColumns(); IList columns = column_dictionary.Select(column => column.Key).ToList(); - if (!columns.Any()) { + if (!columns.Any()) + { columns.Add("add_column_name_here"); } dynamic up = new { remove_index = new { table_name, columns } }; @@ -325,10 +396,11 @@ public void RemoveIndex() { Console.WriteLine(Helpers.Json(output_object)); } - public void Sql() { - dynamic up = String.Join(" ",GenerateColumns().Keys); + public void Sql() + { + dynamic up = String.Join(" ", GenerateColumns().Keys); dynamic down = ""; - dynamic output_object = new { up,down}; + dynamic output_object = new { up, down }; string sql_file_path = CreateFile("ExecuteSQL", output_object); @@ -336,27 +408,33 @@ public void Sql() { Console.WriteLine(Helpers.Json(output_object)); } - public void File() { + public void File() + { string sql_file_path_relative = "..\\sql\\" + String.Join("_", GenerateColumns().Keys); string sql_file_path = Path.Combine(_settings.MigrationsFolder(), sql_file_path_relative); - if(!sql_file_path.ToUpperInvariant().EndsWith(".SQL")) { + if (!sql_file_path.ToUpperInvariant().EndsWith(".SQL")) + { sql_file_path += ".sql"; sql_file_path_relative += ".sql"; } int counter = 0; - while(_file_writer.FileExists(sql_file_path)) { // TODO: This is messy and unreadable, come back and make nice. - if (counter == 0) { + while (_file_writer.FileExists(sql_file_path)) + { // TODO: This is messy and unreadable, come back and make nice. + if (counter == 0) + { sql_file_path = sql_file_path.Replace(".sql", ++counter + ".sql"); sql_file_path_relative = sql_file_path_relative.Replace(".sql", counter + ".sql"); - } else { + } + else + { sql_file_path = sql_file_path.Replace(counter++ + ".sql", counter + ".sql"); sql_file_path_relative = sql_file_path_relative.Replace((counter - 1) + ".sql", counter + ".sql"); } } string text_path = sql_file_path_relative.Replace("..\\", ""); - dynamic up = new { file = sql_file_path_relative }; + dynamic up = new { file = sql_file_path_relative }; dynamic output_object = new { up }; _file_writer.WriteFile(sql_file_path, "-- Execute SQLFile Migration " + text_path); CreateFile("SQLFile_" + String.Join("_", GenerateColumns().Keys), output_object); @@ -364,21 +442,27 @@ public void File() { Console.WriteLine("Generating Migration " + text_path); Console.WriteLine(Helpers.Json(output_object)); } - public void FileSmo() { + public void FileSmo() + { string sql_file_path_relative = "..\\sql\\" + String.Join("_", GenerateColumns().Keys); string sql_file_path = Path.Combine(_settings.MigrationsFolder(), sql_file_path_relative); - if (!sql_file_path.ToUpperInvariant().EndsWith(".SQL")) { + if (!sql_file_path.ToUpperInvariant().EndsWith(".SQL")) + { sql_file_path += ".sql"; sql_file_path_relative += ".sql"; } int counter = 0; - while (_file_writer.FileExists(sql_file_path)) { // TODO: This is messy and unreadable, come back and make nice. - if (counter == 0) { + while (_file_writer.FileExists(sql_file_path)) + { // TODO: This is messy and unreadable, come back and make nice. + if (counter == 0) + { sql_file_path = sql_file_path.Replace(".sql", ++counter + ".sql"); sql_file_path_relative = sql_file_path_relative.Replace(".sql", counter + ".sql"); - } else { + } + else + { sql_file_path = sql_file_path.Replace(counter++ + ".sql", counter + ".sql"); sql_file_path_relative = sql_file_path_relative.Replace((counter - 1) + ".sql", counter + ".sql"); } @@ -399,29 +483,39 @@ public void FileSmo() { /// sometimes used just for the names, and not the value (type) /// /// - private Dictionary GenerateColumns(Dictionary nullable_values = null, Dictionary default_values = null) { + private Dictionary GenerateColumns(Dictionary nullable_values = null, Dictionary default_values = null) + { var rv = new Dictionary(); // rv is return value. don't hate for the acronym nullable_values = nullable_values ?? new Dictionary(); default_values = default_values ?? new Dictionary(); var extra_array = _configuration.Extra.Except(new[] { _configuration.GenerateString }); - foreach (var item in extra_array) { - if (item.Contains(":")) { + foreach (var item in extra_array) + { + if (item.Contains(":")) + { var parts = item.Trim().Split(":".ToCharArray()); rv.Add(parts[0].TrimEnd(), parts[1].TrimStart()); - if(parts.Length > 2 && !string.IsNullOrWhiteSpace(parts[2])) { + if (parts.Length > 2 && !string.IsNullOrWhiteSpace(parts[2])) + { bool nullable = false; - if(bool.TryParse(parts[2].Trim(),out nullable)) { - - } else { + if (bool.TryParse(parts[2].Trim(), out nullable)) + { + + } + else + { nullable = true; } - nullable_values.Add(parts[0].TrimEnd(),nullable); + nullable_values.Add(parts[0].TrimEnd(), nullable); } - if(parts.Length > 3 && !string.IsNullOrWhiteSpace(parts[3])) { - default_values.Add(parts[0].TrimEnd(),parts[3].Trim()); + if (parts.Length > 3 && !string.IsNullOrWhiteSpace(parts[3])) + { + default_values.Add(parts[0].TrimEnd(), parts[3].Trim()); } - } else { + } + else + { // default to string if they dont' specify type rv.Add(item.Trim(), "string"); } diff --git a/Humpback/Parts/Helpers.cs b/Humpback/Parts/Helpers.cs index a400eb9..6e065f4 100644 --- a/Humpback/Parts/Helpers.cs +++ b/Humpback/Parts/Helpers.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; +using Humpback.Tools; +using System; using System.Linq; -using System.Text; using System.Web.Script.Serialization; -using Humpback.Tools; -namespace Humpback.Parts { - public static class Helpers { +namespace Humpback.Parts +{ + public static class Helpers + { private static string[] keywords_tab_level_1 = new[] { "up","down" @@ -19,7 +19,8 @@ public static class Helpers { }; // Here be formatting dragons - public static string Json(dynamic input) { + public static string Json(dynamic input) + { string json = new JavaScriptSerializer().Serialize(input); json = keywords_tab_level_1.Aggregate(json, (current, s) => current.Replace("\"" + s + "\":", Environment.NewLine + "\t\"" + s + "\":")); json = keywords_tab_level_2.Aggregate(json, (current, s) => current.Replace("\"" + s + "\":", Environment.NewLine + "\t\t\"" + s + "\":")); @@ -31,7 +32,8 @@ public static string Json(dynamic input) { } - public static dynamic DeserializeMigration(string this_migration_contents) { + public static dynamic DeserializeMigration(string this_migration_contents) + { var serializer = new JavaScriptSerializer(); serializer.RegisterConverters(new[] { new DynamicJsonConverter() }); diff --git a/Humpback/Parts/SQLCEDatabaseProvider.cs b/Humpback/Parts/HumbackDatabaseProvider.cs similarity index 58% rename from Humpback/Parts/SQLCEDatabaseProvider.cs rename to Humpback/Parts/HumbackDatabaseProvider.cs index 16ee87a..c995c6d 100644 --- a/Humpback/Parts/SQLCEDatabaseProvider.cs +++ b/Humpback/Parts/HumbackDatabaseProvider.cs @@ -1,114 +1,144 @@ -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Data.SqlServerCe; -using System.Linq; -using System.Text; -using Humpback.ConfigurationOptions; +using Humpback.ConfigurationOptions; using Humpback.Interfaces; +using System; +using System.Data.SqlClient; -namespace Humpback.Parts { - public class SQLCEDatabaseProvider : IDatabaseProvider { +namespace Humpback.Parts +{ + public class HumpbackDatabaseProvider : IDatabaseProvider + { private Configuration _configuration; private Settings _settings; private ISqlFormatter _sql_formatter; - private SqlCeConnection GetOpenConnection() { - var rv = new SqlCeConnection(_settings.ConnectionString()); + private SqlConnection GetOpenConnection() + { + var rv = new SqlConnection(_settings.ConnectionString()); rv.Open(); return rv; } - public SQLCEDatabaseProvider(Configuration configuration, Settings settings, ISqlFormatter sql_formatter) { + public HumpbackDatabaseProvider(Configuration configuration, Settings settings, ISqlFormatter sql_formatter) + { _configuration = configuration; _settings = settings; _sql_formatter = sql_formatter; } - public void UpdateMigrationVersion(int number) { - ExecuteCommand(_sql_formatter.sql_update_schema_info(number)); + public void UpdateMigrationVersion(int number) + { + ExecuteCommand(_sql_formatter.sql_update_schema_info(number)); } - public int ExecuteUpCommand(dynamic up) { + public int ExecuteUpCommand(dynamic up) + { var sql = _sql_formatter.GenerateSQLUp(up); - using (var connection = GetOpenConnection()) { + using (var connection = GetOpenConnection()) + { var transaction = connection.BeginTransaction(System.Data.IsolationLevel.Serializable); var cmd = connection.CreateCommand(); cmd.Transaction = transaction; - try { - foreach (var s in sql) { + try + { + foreach (var s in sql) + { - if (_configuration.Verbose) { + if (_configuration.Verbose) + { Console.WriteLine("Executing SQL: " + s); } cmd.CommandText = s; cmd.ExecuteNonQuery(); } transaction.Commit(); - } catch { + } + catch + { transaction.Rollback(); throw; - } finally { + } + finally + { connection.Close(); } } return sql.Length; } - public int ExecuteDownCommand(dynamic down) { + public int ExecuteDownCommand(dynamic down) + { var sql = _sql_formatter.GenerateSQLDown(down); - using (var connection = GetOpenConnection()) { + using (var connection = GetOpenConnection()) + { var transaction = connection.BeginTransaction(System.Data.IsolationLevel.Serializable); var cmd = connection.CreateCommand(); cmd.Transaction = transaction; - try { - foreach (var s in sql) { + try + { + foreach (var s in sql) + { - if (_configuration.Verbose) { + if (_configuration.Verbose) + { Console.WriteLine("Executing SQL: " + s); } cmd.CommandText = s; cmd.ExecuteNonQuery(); } transaction.Commit(); - } catch { + } + catch + { transaction.Rollback(); throw; - } finally { + } + finally + { connection.Close(); } } return sql.Length; } - private int ExecuteCommand(string command) { - if (string.IsNullOrWhiteSpace(command)) { + private int ExecuteCommand(string command) + { + if (string.IsNullOrWhiteSpace(command)) + { return 0; } - using (var connection = GetOpenConnection()) { - using (var cmd = connection.CreateCommand()) { + using (var connection = GetOpenConnection()) + { + using (var cmd = connection.CreateCommand()) + { cmd.CommandText = command; - if (_configuration.Verbose) { + if (_configuration.Verbose) + { Console.WriteLine("Executing SQL: " + command); } return cmd.ExecuteNonQuery(); } } } - public int GetMigrationVersion() { - try { - using (var connection = GetOpenConnection()) { - using (var cmd = connection.CreateCommand()) { + public int GetMigrationVersion() + { + try + { + using (var connection = GetOpenConnection()) + { + using (var cmd = connection.CreateCommand()) + { cmd.CommandText = _sql_formatter.sql_get_schema_info; var reader = cmd.ExecuteReader(); - if (reader.HasRows && reader.Read()) { + if (reader.HasRows && reader.Read()) + { var rv = reader.GetInt32(0); reader.Close(); return rv; } reader.Close(); - using (var cmd_init = connection.CreateCommand()) { + using (var cmd_init = connection.CreateCommand()) + { cmd_init.CommandText = _sql_formatter.sql_initialize_schema_info; cmd.ExecuteNonQuery(); } @@ -116,17 +146,23 @@ public int GetMigrationVersion() { } } - } catch { + } + catch + { EnsureSchemaInfo(); return 0; } } - private void EnsureSchemaInfo() { - try { + private void EnsureSchemaInfo() + { + try + { ExecuteCommand(_sql_formatter.sql_get_schema_info); - } catch { + } + catch + { ExecuteCommand(_sql_formatter.sql_create_schema_info_table); ExecuteCommand(_sql_formatter.sql_initialize_schema_info); } diff --git a/Humpback/Parts/JsonFileMigrationProvider.cs b/Humpback/Parts/JsonFileMigrationProvider.cs index e1b1ce9..39a4ded 100644 --- a/Humpback/Parts/JsonFileMigrationProvider.cs +++ b/Humpback/Parts/JsonFileMigrationProvider.cs @@ -1,70 +1,84 @@ -using System; +using Humpback.ConfigurationOptions; +using Humpback.Interfaces; +using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; -using System.Linq; -using System.Text; -using Humpback.ConfigurationOptions; -using Humpback.Interfaces; -namespace Humpback.Parts { - public class JsonFileMigrationProvider : IMigrationProvider { +namespace Humpback.Parts +{ + public class JsonFileMigrationProvider : IMigrationProvider + { private Configuration _configuration; private IDatabaseProvider _database_provider; private SortedDictionary _migrations; private SortedDictionary _migration_contents; private Settings _settings; - public JsonFileMigrationProvider(Configuration configuration, Settings settings, IDatabaseProvider database_provider) { + public JsonFileMigrationProvider(Configuration configuration, Settings settings, IDatabaseProvider database_provider) + { _configuration = configuration; _settings = settings; _database_provider = database_provider; } - public SortedDictionary GetMigrations() { - if (_migrations == null) { + public SortedDictionary GetMigrations() + { + if (_migrations == null) + { _migrations = new SortedDictionary(); var tmp_migrations = new SortedDictionary(); - foreach (string file in Directory.GetFiles(_settings.MigrationsFolder())) { - if (new FileInfo(file).Extension.Equals(".js", StringComparison.InvariantCultureIgnoreCase)) { + foreach (string file in Directory.GetFiles(_settings.MigrationsFolder())) + { + if (new FileInfo(file).Extension.Equals(".js", StringComparison.InvariantCultureIgnoreCase)) + { tmp_migrations.Add(file, file); } } int ctr = 1; - foreach(var key in tmp_migrations.Keys) { + foreach (var key in tmp_migrations.Keys) + { _migrations.Add(ctr++, key); } } return _migrations; } - public SortedDictionary GetMigrationsContents() { - if (_migration_contents == null) { + public SortedDictionary GetMigrationsContents() + { + if (_migration_contents == null) + { _migration_contents = new SortedDictionary(); - foreach (var kvp in GetMigrations()) { // kvp is key value pair. + foreach (var kvp in GetMigrations()) + { // kvp is key value pair. _migration_contents.Add(kvp.Key, File.ReadAllText(kvp.Value)); } } return _migration_contents; } - public KeyValuePair GetMigrationWithContents(int migration_number) { + public KeyValuePair GetMigrationWithContents(int migration_number) + { string filename = GetMigrations()[migration_number]; var contents = ""; - if(_migration_contents == null) { + if (_migration_contents == null) + { contents = File.ReadAllText(filename); - } else { + } + else + { contents = GetMigrationsContents()[migration_number]; } return new KeyValuePair(filename, contents); } - public int DatabaseMigrationNumber() { + public int DatabaseMigrationNumber() + { return _database_provider.GetMigrationVersion(); } - public void SetMigrationNumber(int number) { + public void SetMigrationNumber(int number) + { _database_provider.UpdateMigrationVersion(number); } } diff --git a/Humpback/Parts/Migrate.cs b/Humpback/Parts/Migrate.cs index 390bf25..0d60542 100644 --- a/Humpback/Parts/Migrate.cs +++ b/Humpback/Parts/Migrate.cs @@ -1,83 +1,106 @@ -using System; +using Humpback.Interfaces; +using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using Humpback.Interfaces; -namespace Humpback.Parts { - public class Migrate:IHumpbackCommand { - +namespace Humpback.Parts +{ + public class Migrate : IHumpbackCommand + { + private IDatabaseProvider _database_provider; private IMigrationProvider _migration_provider; private ConfigurationOptions.Configuration _configuration; - public Migrate(ConfigurationOptions.Configuration configuration, IDatabaseProvider database_provider, IMigrationProvider migration_provider) { + public Migrate(ConfigurationOptions.Configuration configuration, IDatabaseProvider database_provider, IMigrationProvider migration_provider) + { _configuration = configuration; _database_provider = database_provider; _migration_provider = migration_provider; } -// > hump -m -all | updates database to most recent migration -// > hump -m 12 | updates database to a specific migration (up or down) -// > hump -m -up | migrates database up one migration -// > hump -m -down | migrates database down one migration -// > hump -m -empty | removes all migrations from database -// > hump -m -reset | removes and re-adds all migrations (-empty, then -all) + // > hump -m -all | updates database to most recent migration + // > hump -m 12 | updates database to a specific migration (up or down) + // > hump -m -up | migrates database up one migration + // > hump -m -down | migrates database down one migration + // > hump -m -empty | removes all migrations from database + // > hump -m -reset | removes and re-adds all migrations (-empty, then -all) - public void Execute() { + public void Execute() + { int top_migration = _migration_provider.GetMigrations().Max(m => m.Key); int current_migration = _migration_provider.DatabaseMigrationNumber(); - if(current_migration > top_migration) { + if (current_migration > top_migration) + { current_migration = top_migration; } - if(_configuration.All) { + if (_configuration.All) + { MigrateTo(top_migration); - } else if (_configuration.Up) { + } + else if (_configuration.Up) + { MigrateTo(++current_migration); - } else if (_configuration.Down) { + } + else if (_configuration.Down) + { MigrateTo(--current_migration); - } else if (_configuration.Empty) { + } + else if (_configuration.Empty) + { MigrateTo(0); - } else if (_configuration.Reset) { + } + else if (_configuration.Reset) + { MigrateTo(0); MigrateTo(top_migration); - } else if (SingleMigrationID() > 0) { + } + else if (SingleMigrationID() > 0) + { MigrateTo(SingleMigrationID()); - } else { + } + else + { MigrateTo(top_migration); } } - private void MigrateTo(int migration) { + private void MigrateTo(int migration) + { var migrations = _migration_provider.GetMigrations(); int current = _migration_provider.DatabaseMigrationNumber(); - if (migrations.Count < current) { + if (migrations.Count < current) + { current = migrations.Count; } - if(migration > migrations.Max(m => m.Key) || migration < 0) { + if (migration > migrations.Max(m => m.Key) || migration < 0) + { Console.WriteLine("Invalid Migration"); return; } - if (migration == current) { + if (migration == current) + { Console.WriteLine("Nothing to be done."); return; } - while(current < migration) { + while (current < migration) + { // go Up KeyValuePair migration_kvp = _migration_provider.GetMigrationWithContents(++current); string migration_json = migration_kvp.Value; dynamic migration_object = Helpers.DeserializeMigration(migration_json); - Console.WriteLine("Executing " +current+". Executing Migration " + migration_kvp.Key); + Console.WriteLine("Executing " + current + ". Executing Migration " + migration_kvp.Key); _database_provider.ExecuteUpCommand(migration_object); _database_provider.UpdateMigrationVersion(current); } - while(current > migration && current > 0) { + while (current > migration && current > 0) + { // go down KeyValuePair migration_kvp = _migration_provider.GetMigrationWithContents(current); string migration_json = migration_kvp.Value; @@ -89,7 +112,8 @@ private void MigrateTo(int migration) { } - private int SingleMigrationID() { + private int SingleMigrationID() + { int migration_id = 0; bool has_extra = _configuration.Extra.Any(); bool extra_is_int = has_extra && int.TryParse(_configuration.Extra.First(), out migration_id); diff --git a/Humpback/Parts/MigrationViewer.cs b/Humpback/Parts/MigrationViewer.cs index 783f88d..13e645c 100644 --- a/Humpback/Parts/MigrationViewer.cs +++ b/Humpback/Parts/MigrationViewer.cs @@ -1,22 +1,24 @@ -using System; -using System.Collections.Generic; +using Humpback.ConfigurationOptions; +using Humpback.Interfaces; +using System; using System.IO; using System.Linq; -using System.Text; -using Humpback.ConfigurationOptions; -using Humpback.Interfaces; -namespace Humpback.Parts { - public class MigrationViewer : IHumpbackCommand { - +namespace Humpback.Parts +{ + public class MigrationViewer : IHumpbackCommand + { + private IMigrationProvider _migration_provider; private Configuration _configuration; - public MigrationViewer(Configuration configuration, IMigrationProvider migration_provider) { + public MigrationViewer(Configuration configuration, IMigrationProvider migration_provider) + { _migration_provider = migration_provider; _configuration = configuration; } - private void ExecuteList() { + private void ExecuteList() + { Console.WriteLine("==============================="); Console.WriteLine("Humpback Migration List"); var migrations = _migration_provider.GetMigrations(); @@ -39,32 +41,38 @@ private void ExecuteList() { /_,' "); // yes i know thats not actually a humpback whale, its a sperm whale, but for now thats too bad, theres not a lot of ascii whale photos to choose from. // also, if user doesnt' have monospaced font in their shell, it wont render right. bummer for them! - Console.WriteLine(migrations.Count + + Console.WriteLine(migrations.Count + @" Migrations \o/ means it is currently deployed ================================================================="); int db_version = _migration_provider.DatabaseMigrationNumber(); - foreach(var m in migrations) { + foreach (var m in migrations) + { Console.WriteLine("{0} {1} {2}", (m.Key > db_version ? " " : "\\o/"), ((m.Key).ToString()).PadLeft(3), new FileInfo(m.Value).Name); } } - - public void Execute() { + + public void Execute() + { int migration_id = 0; bool has_extra = _configuration.Extra.Any(); bool extra_is_int = has_extra && int.TryParse(_configuration.Extra.First(), out migration_id); bool migration_exists = extra_is_int && _migration_provider.GetMigrations().ContainsKey(migration_id); - if(migration_exists) { + if (migration_exists) + { ExecuteDetail(migration_id); - } else { + } + else + { ExecuteList(); } } - private void ExecuteDetail(int migration_id) { - + private void ExecuteDetail(int migration_id) + { + Console.WriteLine(@" | -.- : __ @@ -74,12 +82,15 @@ private void ExecuteDetail(int migration_id) { "); var migration = _migration_provider.GetMigrationWithContents(migration_id); Console.WriteLine(new FileInfo(migration.Key).Name); - if (migration_id > _migration_provider.DatabaseMigrationNumber()) { + if (migration_id > _migration_provider.DatabaseMigrationNumber()) + { Console.WriteLine("Migration is NOT currently deployed"); - } else { + } + else + { Console.WriteLine("Migration IS currently deployed \\o/"); } - Console.WriteLine( "===================================="); + Console.WriteLine("===================================="); Console.WriteLine(migration.Value); Console.WriteLine(); } diff --git a/Humpback/Parts/SQLDatabaseProvider.cs b/Humpback/Parts/SQLDatabaseProvider.cs index 330ffed..c2f0723 100644 --- a/Humpback/Parts/SQLDatabaseProvider.cs +++ b/Humpback/Parts/SQLDatabaseProvider.cs @@ -1,68 +1,81 @@ -using System; +using Humpback.Interfaces; +using System; using System.Collections.Generic; using System.Data.SqlClient; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Resources; -using System.Text; -using Humpback.Interfaces; using Configuration = Humpback.ConfigurationOptions.Configuration; using Settings = Humpback.ConfigurationOptions.Settings; -namespace Humpback.Parts { - public class SQLDatabaseProvider : IDatabaseProvider { +namespace Humpback.Parts +{ + public class SQLDatabaseProvider : IDatabaseProvider + { private Configuration _configuration; private Settings _settings; protected ISqlFormatter _sql_formatter; - private SqlConnection GetOpenConnection() { + private SqlConnection GetOpenConnection() + { var rv = new SqlConnection(_settings.ConnectionString()); rv.Open(); return rv; } - public SQLDatabaseProvider(Configuration configuration, Settings settings, ISqlFormatter sql_formatter) { + public SQLDatabaseProvider(Configuration configuration, Settings settings, ISqlFormatter sql_formatter) + { _configuration = configuration; _settings = settings; _sql_formatter = sql_formatter; } - public void UpdateMigrationVersion(int number) { - ExecuteCommand(_sql_formatter.sql_update_schema_info(number)); + public void UpdateMigrationVersion(int number) + { + ExecuteCommand(_sql_formatter.sql_update_schema_info(number)); } - public virtual int ExecuteUpCommand(dynamic up) { + public virtual int ExecuteUpCommand(dynamic up) + { var sql = _sql_formatter.GenerateSQLUp(up); // test for file bool has_filesmo = false; - try { + try + { bool fsmo = up.up.filesmo != null; has_filesmo = fsmo; - } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) { + } + catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) + { // intentionally let thru, no smo object } - if (has_filesmo) { - ExecuteSmo(_settings.ConnectionString(), sql[0]); + if (has_filesmo) + { + Smo.Executor.Execute(_settings.ConnectionString(), sql[0]); return 1; - } else { - using (var connection = GetOpenConnection()) { + } + else + { + using (var connection = GetOpenConnection()) + { var transaction = connection.BeginTransaction(System.Data.IsolationLevel.Serializable); var cmd = connection.CreateCommand(); cmd.Transaction = transaction; - try { - foreach (var s in sql) { + try + { + foreach (var s in sql) + { - if (s.Contains("DROP TABLE")) { + if (s.Contains("DROP TABLE")) + { - if (_configuration.Verbose) { + if (_configuration.Verbose) + { Console.WriteLine("DROPPING CONSTRAINTS BEFORE Executing SQL: " + s); } string table_name = s.Replace("DROP TABLE ", "").Trim(); - foreach (var drop_string in DropTableConstraints(table_name, cmd)) { + foreach (var drop_string in DropTableConstraints(table_name, cmd)) + { cmd.CommandText = drop_string; cmd.ExecuteNonQuery(); } @@ -70,17 +83,22 @@ public virtual int ExecuteUpCommand(dynamic up) { } - if (_configuration.Verbose) { + if (_configuration.Verbose) + { Console.WriteLine("Executing SQL: " + s); } cmd.CommandText = s; cmd.ExecuteNonQuery(); } transaction.Commit(); - } catch { + } + catch + { transaction.Rollback(); throw; - } finally { + } + finally + { connection.Close(); } } @@ -88,100 +106,88 @@ public virtual int ExecuteUpCommand(dynamic up) { } } - // due to dependency, kinda pulling this out on an as needed basis - // this way if someone doenst' have smo, and doesnt try to call, never has an issue. - private int ExecuteSmo(string connection_string, string sql) { - // Smo.Executor.Execute(_settings.ConnectionString(), sql[0]); - if(smo_assembly == null) { - load_smo_assembly(); - } - var Executor = smo_assembly.GetType("Humpback.Smo.Executor"); - var Execute = Executor.GetMethod("Execute"); - return (int)Execute.Invoke(null, new[] { connection_string, sql }); - } - - private void load_smo_assembly() { - var _assembly = Assembly.GetExecutingAssembly(); - using(var resource_stream = _assembly.GetManifestResourceStream("Humpback.Artifacts.Humpback.Smo.dll")) { - smo_assembly = Assembly.Load(ReadFully(resource_stream)); - } - } - - // Thank you Jon Skeet! http://stackoverflow.com/questions/221925/creating-a-byte-array-from-a-stream/221941#221941 - public static byte[] ReadFully(Stream input) { - var buffer = new byte[16 * 1024]; - using (var ms = new MemoryStream()) { - int read; - while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { - ms.Write(buffer, 0, read); - } - return ms.ToArray(); - } - } - private Assembly smo_assembly; - - public virtual int ExecuteDownCommand(dynamic down) { - if(down.down == null) { + public virtual int ExecuteDownCommand(dynamic down) + { + if (down.down == null) + { return 0; } var sql = _sql_formatter.GenerateSQLDown(down); bool has_filesmo = false; - try { + try + { bool fsmo = down.down.filesmo != null; has_filesmo = fsmo; - } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) { + } + catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) + { // intentionally let thru, no smo object } - if (has_filesmo) { - ExecuteSmo(_settings.ConnectionString(), sql[0]); + if (has_filesmo) + { + Smo.Executor.Execute(_settings.ConnectionString(), sql[0]); return 1; } - using (var connection = GetOpenConnection()) { + using (var connection = GetOpenConnection()) + { var transaction = connection.BeginTransaction(System.Data.IsolationLevel.Serializable); var cmd = connection.CreateCommand(); cmd.Transaction = transaction; - try { - foreach (var s in sql) { - if (s.Contains("DROP TABLE")) { + try + { + foreach (var s in sql) + { + if (s.Contains("DROP TABLE")) + { - if (_configuration.Verbose) { + if (_configuration.Verbose) + { Console.WriteLine("DROPPING CONSTRAINTS BEFORE Executing SQL: " + s); } string table_name = s.Replace("DROP TABLE ", "").Trim(); - foreach (var drop_string in DropTableConstraints(table_name, cmd)) { + foreach (var drop_string in DropTableConstraints(table_name, cmd)) + { cmd.CommandText = drop_string; cmd.ExecuteNonQuery(); } } - if (_configuration.Verbose) { + if (_configuration.Verbose) + { Console.WriteLine("Executing SQL: " + s); } cmd.CommandText = s; cmd.ExecuteNonQuery(); } transaction.Commit(); - } catch { + } + catch + { transaction.Rollback(); throw; - } finally { + } + finally + { connection.Close(); } } return sql.Length; } - private IEnumerable DropTableConstraints(string table_name, SqlCommand cmd) { + private IEnumerable DropTableConstraints(string table_name, SqlCommand cmd) + { string constraint_select = string.Format( "SELECT a.name FROM sys.objects a INNER JOIN sys.objects b ON a.parent_object_id = b.object_id WHERE b.name = '{0}'", - table_name.Replace("[","").Replace("]","")); + table_name.Replace("[", "").Replace("]", "")); cmd.CommandText = constraint_select; var rv = new List(); - using (var reader = cmd.ExecuteReader()) { - while (reader.Read()) { + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { rv.Add(string.Format("ALTER TABLE {0} DROP CONSTRAINT [{1}]", table_name, reader[0])); } reader.Close(); @@ -189,35 +195,46 @@ private IEnumerable DropTableConstraints(string table_name, SqlCommand c return rv; } - protected virtual int ExecuteCommand(string command) { - if (string.IsNullOrWhiteSpace(command)) { + protected virtual int ExecuteCommand(string command) + { + if (string.IsNullOrWhiteSpace(command)) + { return 0; } - using (var connection = GetOpenConnection()) { - using (var cmd = connection.CreateCommand()) { + using (var connection = GetOpenConnection()) + { + using (var cmd = connection.CreateCommand()) + { cmd.CommandText = command; - if (_configuration.Verbose) { + if (_configuration.Verbose) + { Console.WriteLine("Executing SQL: " + command); } return cmd.ExecuteNonQuery(); } } } - - public int GetMigrationVersion() { - try { - using (var connection = GetOpenConnection()) { - using (var cmd = connection.CreateCommand()) { + + public int GetMigrationVersion() + { + try + { + using (var connection = GetOpenConnection()) + { + using (var cmd = connection.CreateCommand()) + { cmd.CommandText = _sql_formatter.sql_get_schema_info; var reader = cmd.ExecuteReader(); - if (reader.HasRows && reader.Read()) { + if (reader.HasRows && reader.Read()) + { var rv = reader.GetInt32(0); reader.Close(); return rv; } reader.Close(); - using (var cmd_init = connection.CreateCommand()) { + using (var cmd_init = connection.CreateCommand()) + { cmd_init.CommandText = _sql_formatter.sql_initialize_schema_info; cmd.ExecuteNonQuery(); } @@ -225,22 +242,25 @@ public int GetMigrationVersion() { } } - } catch { + } + catch + { EnsureSchemaInfo(); return 0; } } - - private void EnsureSchemaInfo() { - try { + private void EnsureSchemaInfo() + { + try + { ExecuteCommand(_sql_formatter.sql_get_schema_info); - } catch { + } + catch + { ExecuteCommand(_sql_formatter.sql_create_schema_info_table); ExecuteCommand(_sql_formatter.sql_initialize_schema_info); } } - - } } diff --git a/Humpback/Parts/SQLServerFormatter.cs b/Humpback/Parts/SQLServerFormatter.cs index 7809d07..b93af42 100644 --- a/Humpback/Parts/SQLServerFormatter.cs +++ b/Humpback/Parts/SQLServerFormatter.cs @@ -1,125 +1,162 @@ -using System; +using Humpback.ConfigurationOptions; +using Humpback.Interfaces; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using Humpback.ConfigurationOptions; -using Humpback.Interfaces; -namespace Humpback.Parts { - public class SQLServerFormatter : ISqlFormatter { +namespace Humpback.Parts +{ + public class SQLServerFormatter : ISqlFormatter + { private Configuration _configuration; private Settings _settings; private List _commands_to_add; - public SQLServerFormatter(Configuration configuration, Settings settings) { + public SQLServerFormatter(Configuration configuration, Settings settings) + { _configuration = configuration; _settings = settings; _commands_to_add = new List(); } - public string[] GenerateSQLUp(dynamic operation) { - if (operation.up != null) { + public string[] GenerateSQLUp(dynamic operation) + { + if (operation.up != null) + { return ((IEnumerable)GetCommands(operation.up)).ToArray(); } return new string[0]; } - public string[] GenerateSQLDown(dynamic operation) { - if (operation.down != null) { + public string[] GenerateSQLDown(dynamic operation) + { + if (operation.down != null) + { return ((IEnumerable)GetCommands(operation.down)).ToArray(); } - if (operation.up != null) { + if (operation.up != null) + { return ((IEnumerable)GetReadMinds(operation.up)).Reverse().ToArray(); } return new string[0]; } - public string sql_file_name(string p) { + public string sql_file_name(string p) + { return p.Substring(0, p.Length - 3) + ".sql"; } - public string sql_create_schema_info_table { + public string sql_create_schema_info_table + { get { return "CREATE TABLE SchemaInfo (Version INT NOT NULL PRIMARY KEY)"; } } - public string sql_initialize_schema_info { + public string sql_initialize_schema_info + { get { return "INSERT INTO SchemaInfo(Version) VALUES(0)"; } } - public string sql_update_schema_info(int version) { + public string sql_update_schema_info(int version) + { return String.Format("UPDATE SchemaInfo SET Version = {0}", version); } - public string sql_get_schema_info { + public string sql_get_schema_info + { get { return "SELECT Version FROM SchemaInfo"; } } - public string sql_fs_foreign_key { - get { + public string sql_fs_foreign_key + { + get + { return "ALTER TABLE [{1}] ADD CONSTRAINT [{0}] FOREIGN KEY ([{2}]) REFERENCES [{3}] ([Id]) ON DELETE NO ACTION ON UPDATE NO ACTION;"; } } - public string sql_fs_foreign_key_name { - get { + public string sql_fs_foreign_key_name + { + get + { return "FK_{0}_{1}_{2}"; } } - public string sql_fs_Timestamps { - get { + public string sql_fs_Timestamps + { + get + { return "\n\t, CreatedOn datetime DEFAULT getutcdate() NOT NULL\n\t, UpdatedOn datetime DEFAULT getutcdate() NOT NULL"; } } - public string sql_fs_FullAudit { - get { + public string sql_fs_FullAudit + { + get + { return "\n\t, CreatedOn datetime DEFAULT getutcdate() NOT NULL\n\t, UpdatedOn datetime DEFAULT getutcdate() NOT NULL, CreatedBy nvarchar(1000) NULL, UpdatedBy nvarchar(1000) NULL"; } } - public string sql_fs_primary_key { - get { + public string sql_fs_primary_key + { + get + { return "Id int PRIMARY KEY IDENTITY(1,1) NOT NULL \n\t"; } } - public string sql_fs_create_table { - get { + public string sql_fs_create_table + { + get + { return "CREATE TABLE [{0}]\r\n\t ({1}) "; } } - public string sql_fs_drop_table { - get { + public string sql_fs_drop_table + { + get + { return "DROP TABLE [{0}]"; } } - public string sql_fs_alter_table_add_column { - get { + public string sql_fs_alter_table_add_column + { + get + { return "ALTER TABLE [{0}] ADD {1} "; } } - public string sql_fs_alter_table_drop_column { - get { + public string sql_fs_alter_table_drop_column + { + get + { return "ALTER TABLE [{0}] DROP COLUMN [{1}]"; } } - public string sql_fs_alter_table_alter_column { - get { + public string sql_fs_alter_table_alter_column + { + get + { return "ALTER TABLE [{0}] ALTER COLUMN {1}"; } } - public string sql_fs_add_index { - get { + public string sql_fs_add_index + { + get + { return "CREATE NONCLUSTERED INDEX [{0}] ON [{1}] ({2} )"; } } - public string sql_fs_drop_index { - get { + public string sql_fs_drop_index + { + get + { return "DROP INDEX [{0}].[{1}]"; } } @@ -128,9 +165,11 @@ public string sql_fs_drop_index { /// /// This is where the shorthand types are deciphered. Fix/love/tweak as you will /// - static string SetColumnType(string colType) { + static string SetColumnType(string colType) + { - if (!colType.Equals("datetime")) { + if (!colType.Equals("datetime")) + { colType = colType.Replace("date", "datetime"); } @@ -147,30 +186,35 @@ static string SetColumnType(string colType) { /// /// Build a list of columns from the past-in array in the JSON file /// - private string BuildColumnList(string table_name, dynamic columns) { + private string BuildColumnList(string table_name, dynamic columns) + { //holds the output var sb = new StringBuilder(); var counter = 0; - foreach (dynamic col in columns) { + foreach (dynamic col in columns) + { //name bool nullable_specified = false; string column_name = col.name; string column_type = col.type; - if(col.nullable != null) { + if (col.nullable != null) + { nullable_specified = true; } bool nullable = col.nullable ?? true; string default_value = col.@default ?? ""; string extra_col_def = col.extra ?? ""; - if (col.type != null && col.type.ToLower() == "reference") { + if (col.type != null && col.type.ToLower() == "reference") + { string id_col_name = col.name + "Id"; column_name = id_col_name; column_type = "INT"; string fk_name = string.Format(sql_fs_foreign_key_name, table_name.ToLower(), col.name.ToLower(), id_col_name.ToLower()); // FK_Orders_User_UserId string fk = string.Format(sql_fs_foreign_key, fk_name, table_name, id_col_name, col.name); _commands_to_add.Add(fk); - if (!nullable_specified) { + if (!nullable_specified) + { nullable = false; } } @@ -182,23 +226,30 @@ private string BuildColumnList(string table_name, dynamic columns) { sb.Append(SetColumnType(column_type)); //nullability - don't set if this is the Primary Key - if (column_type != "pk") { - if (nullable) { + if (column_type != "pk") + { + if (nullable) + { sb.Append(" NULL "); - } else { + } + else + { sb.Append(" NOT NULL "); } - if (!string.IsNullOrWhiteSpace(default_value)) { + if (!string.IsNullOrWhiteSpace(default_value)) + { sb.Append(" DEFAULT (" + default_value + ") "); } - if (!string.IsNullOrWhiteSpace(extra_col_def)) { + if (!string.IsNullOrWhiteSpace(extra_col_def)) + { sb.Append(extra_col_def); } } counter++; //this format will indent the column - if (counter < columns.Count) { + if (counter < columns.Count) + { sb.Append("\r\n\t"); } @@ -210,7 +261,8 @@ private string BuildColumnList(string table_name, dynamic columns) { /// Strip out the leading comma. Wish there was a more elegant way to do this /// and no, Regex doesn't count /// - static string StripLeadingComma(string columns) { + static string StripLeadingComma(string columns) + { if (columns.StartsWith(", ")) return columns.Substring(2, columns.Length - 2); return columns; @@ -219,9 +271,11 @@ static string StripLeadingComma(string columns) { /// /// create unique name for index based on table and columns specified /// - public string CreateIndexName(dynamic ix) { + public string CreateIndexName(dynamic ix) + { var sb = new StringBuilder(); - foreach (dynamic c in ix.columns) { + foreach (dynamic c in ix.columns) + { sb.AppendFormat("{1}{0}", c.Replace(" ", "_"), (sb.Length == 0 ? "" : "_")); // ternary to only add underscore if not first iteration } return string.Format("IX_{0}_{1}", ix.table_name, sb.ToString()); @@ -230,9 +284,11 @@ public string CreateIndexName(dynamic ix) { /// /// create string for columns /// - public string CreateIndexColumnString(dynamic columns) { + public string CreateIndexColumnString(dynamic columns) + { var sb = new StringBuilder(); - foreach (dynamic c in columns) { + foreach (dynamic c in columns) + { sb.AppendFormat("{1} [{0}] ASC", c, (sb.Length == 0 ? "" : ",")); // ternary to only add comma if not first iteration } return sb.ToString(); @@ -240,38 +296,52 @@ public string CreateIndexColumnString(dynamic columns) { // wrapped the get command to accomodate optional arrays of operations OR just a single op - private IEnumerable GetCommands(dynamic op) { + private IEnumerable GetCommands(dynamic op) + { _commands_to_add = new List(); bool failed_count = false; - try { + try + { var isnull = op.Count != null; - } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) { + } + catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) + { failed_count = true; } - if (failed_count) { + if (failed_count) + { yield return GetCommand(op); - } else { - if (op.Count != null) { - foreach (var iter_op in op) { + } + else + { + if (op.Count != null) + { + foreach (var iter_op in op) + { yield return GetCommand(iter_op); } - } else { + } + else + { yield return GetCommand(op); } } - if (_commands_to_add.Count > 0) { // post main commands here, i.e. FK's - foreach (var cmd in _commands_to_add) { + if (_commands_to_add.Count > 0) + { // post main commands here, i.e. FK's + foreach (var cmd in _commands_to_add) + { yield return cmd; } } } - private string GetCommand(dynamic op) { + private string GetCommand(dynamic op) + { //the "op" here is an "up" or a "down". It's dynamic as that's what the JSON parser //will return. The neat thing about this parser is that the dynamic result will //return null if the key isn't present - so it's a simple null check for the operations/keys we need. @@ -288,22 +358,31 @@ private string GetCommand(dynamic op) { return SetColumnType(op).Replace("{", "").Replace("}", ""); //CREATE - if (op.create_table != null) { + if (op.create_table != null) + { var columns = BuildColumnList(op.create_table.name, op.create_table.columns); //add some timestamps? - if (op.create_table.full_audit ?? false) { + if (op.create_table.full_audit ?? false) + { columns += sql_fs_FullAudit; - } else if (op.create_table.timestamps != null) { + } + else if (op.create_table.timestamps != null) + { columns += sql_fs_Timestamps; } //make sure we have a PK :) - if (!columns.Contains("PRIMARY KEY") & !columns.Contains("IDENTITY")) { + if (!columns.Contains("PRIMARY KEY") & !columns.Contains("IDENTITY")) + { columns = sql_fs_primary_key + columns; - } else { - foreach (var col in op.create_table.columns) { - if (col.type.ToString() == "pk") { + } + else + { + foreach (var col in op.create_table.columns) + { + if (col.type.ToString() == "pk") + { pkName = col.name; break; } @@ -313,28 +392,46 @@ private string GetCommand(dynamic op) { result = string.Format(sql_fs_create_table, op.create_table.name, columns); //DROP - } else if (op.drop_table != null) { + } + else if (op.drop_table != null) + { return string.Format(sql_fs_drop_table, op.drop_table); //ADD COLUMN - } else if (op.add_column != null) { + } + else if (op.add_column != null) + { result = string.Format(sql_fs_alter_table_add_column, op.add_column.table, StripLeadingComma(BuildColumnList(op.add_column.table, op.add_column.columns))); //DROP COLUMN - } else if (op.remove_column != null) { + } + else if (op.remove_column != null) + { result = string.Format(sql_fs_alter_table_drop_column, op.remove_column.table, op.remove_column.column); //CHANGE - } else if (op.change_column != null) { + } + else if (op.change_column != null) + { result = string.Format(sql_fs_alter_table_alter_column, op.change_column.table, StripLeadingComma(BuildColumnList(op.change_column.table, op.change_column.columns))); //ADD INDEX - } else if (op.add_index != null) { + } + else if (op.add_index != null) + { result = string.Format(sql_fs_add_index, CreateIndexName(op.add_index), op.add_index.table_name, CreateIndexColumnString(op.add_index.columns)); //REMOVE INDEX - } else if (op.remove_index != null) { + } + else if (op.remove_index != null) + { result = string.Format(sql_fs_drop_index, op.remove_index.table_name, CreateIndexName(op.remove_index)); - } else if (op.execute != null) { + } + else if (op.execute != null) + { result = op.execute; - } else if (op.file != null) { + } + else if (op.file != null) + { result = File.ReadAllText(Path.Combine(_settings.SqlFileFolder(), op.file)); - } else if (op.filesmo != null) { + } + else if (op.filesmo != null) + { result = File.ReadAllText(Path.Combine(_settings.SqlFileFolder(), op.filesmo)); } @@ -343,12 +440,17 @@ private string GetCommand(dynamic op) { - private IEnumerable GetReadMinds(dynamic op) { - if (op.Count != null) { - foreach (var iter_op in op) { + private IEnumerable GetReadMinds(dynamic op) + { + if (op.Count != null) + { + foreach (var iter_op in op) + { yield return ReadMinds(iter_op); } - } else { + } + else + { yield return ReadMinds(op); } } @@ -357,16 +459,20 @@ private IEnumerable GetReadMinds(dynamic op) { /// /// If a "down" isn't declared, this handy function will try and figure it out for you /// - public string ReadMinds(dynamic up) { + public string ReadMinds(dynamic up) + { //CREATE - if (up.create_table != null) { + if (up.create_table != null) + { return string.Format(sql_fs_drop_table, up.create_table.name); //DROP COLUMN } - if (up.add_column != null) { + if (up.add_column != null) + { return string.Format(sql_fs_alter_table_drop_column, up.add_column.table, up.add_column.columns[0].name); } - if (up.add_index != null) { + if (up.add_index != null) + { // DROP INDEX return string.Format(sql_fs_drop_index, up.add_index.table_name, CreateIndexName(up.add_index)); } diff --git a/Humpback/Parts/SettingsActions.cs b/Humpback/Parts/SettingsActions.cs index dbb7a02..dae3e52 100644 --- a/Humpback/Parts/SettingsActions.cs +++ b/Humpback/Parts/SettingsActions.cs @@ -1,59 +1,77 @@ -using System; -using System.Collections.Generic; +using Humpback.ConfigurationOptions; +using System; using System.Linq; -using System.Text; -using Humpback.ConfigurationOptions; -namespace Humpback.Parts { - public class SettingsActions : IHumpbackCommand { +namespace Humpback.Parts +{ + public class SettingsActions : IHumpbackCommand + { private Configuration _configuraion; private Settings _current_settings; - public SettingsActions(Configuration configuration, Settings current_settings) { + public SettingsActions(Configuration configuration, Settings current_settings) + { _configuraion = configuration; _current_settings = current_settings; } - public void Execute() { + public void Execute() + { Console.WriteLine(@" Humpback Migration Settings =========================== "); - if (!String.IsNullOrWhiteSpace(_configuraion.new_project_name)) { - _current_settings.AddProject(_configuraion.new_project_name); - } else if (_configuraion.env_init) { - if (!_current_settings.Projects.Any(p => p.name.Equals("default", StringComparison.OrdinalIgnoreCase))) { - _current_settings.AddProject("default"); - } else { - string new_name = ""; - new_name = AskForProjectName(); - _current_settings.AddProject(new_name); - } - } - if (!String.IsNullOrWhiteSpace(_configuraion.settings_cs)) { - _current_settings.SetConnectionString(_configuraion.settings_cs); - } - if (!String.IsNullOrWhiteSpace(_configuraion.settings_dir)) { - _current_settings.SetDirectory(_configuraion.settings_dir); - } - if (!String.IsNullOrWhiteSpace(_configuraion.settings_flavor)) { - _current_settings.SetFlavor(_configuraion.settings_flavor); - } - if (!String.IsNullOrWhiteSpace(_configuraion.settings_rename)) { - _current_settings.Rename(_configuraion.settings_rename); - } - if (!String.IsNullOrWhiteSpace(_configuraion.remove_project_name)) { - _current_settings.Remove(_configuraion.remove_project_name); + if (!String.IsNullOrWhiteSpace(_configuraion.new_project_name)) + { + _current_settings.AddProject(_configuraion.new_project_name); + } + else if (_configuraion.env_init) + { + if (!_current_settings.Projects.Any(p => p.name.Equals("default", StringComparison.OrdinalIgnoreCase))) + { + _current_settings.AddProject("default"); } - if (!String.IsNullOrWhiteSpace(_configuraion.set_current_settings)) { - _current_settings.SetCurrent(_configuraion.set_current_settings); - Console.WriteLine("new current project: " + _configuraion.set_current_settings.ToLower()); + else + { + string new_name = ""; + new_name = AskForProjectName(); + _current_settings.AddProject(new_name); } + } + if (!String.IsNullOrWhiteSpace(_configuraion.settings_cs)) + { + _current_settings.SetConnectionString(_configuraion.settings_cs); + } + if (!String.IsNullOrWhiteSpace(_configuraion.settings_dir)) + { + _current_settings.SetDirectory(_configuraion.settings_dir); + } + if (!String.IsNullOrWhiteSpace(_configuraion.settings_flavor)) + { + _current_settings.SetFlavor(_configuraion.settings_flavor); + } + if (!String.IsNullOrWhiteSpace(_configuraion.settings_rename)) + { + _current_settings.Rename(_configuraion.settings_rename); + } + if (!String.IsNullOrWhiteSpace(_configuraion.remove_project_name)) + { + _current_settings.Remove(_configuraion.remove_project_name); + } + if (!String.IsNullOrWhiteSpace(_configuraion.set_current_settings)) + { + _current_settings.SetCurrent(_configuraion.set_current_settings); + Console.WriteLine("new current project: " + _configuraion.set_current_settings.ToLower()); + } Console.WriteLine("Settings file " + Settings.SettingsFilePath); - foreach(var setting in _current_settings.Projects) { - if (setting.name == _current_settings.CurrentProject) { + foreach (var setting in _current_settings.Projects) + { + if (setting.name == _current_settings.CurrentProject) + { Console.Write(setting.name); Console.WriteLine(" ***"); - } else { + } + else + { Console.WriteLine(setting.name); } Console.WriteLine(" - connection string : " + setting.connection_string); @@ -62,23 +80,27 @@ Humpback Migration Settings } } - private string AskForProjectName() { + private string AskForProjectName() + { string new_name; - do { + do + { Console.Write("Project Name > "); new_name = Console.ReadLine(); - if(_current_settings.Projects.Any( - p => p.name.Equals(new_name, StringComparison.OrdinalIgnoreCase))) { + if (_current_settings.Projects.Any( + p => p.name.Equals(new_name, StringComparison.OrdinalIgnoreCase))) + { Console.WriteLine("That name already exists as a project."); Console.WriteLine("To switch to that project use the command"); Console.WriteLine("hump -env -set " + new_name); Console.WriteLine(); Console.WriteLine("Your existing projects are:"); - foreach(var p in _current_settings.Projects) { + foreach (var p in _current_settings.Projects) + { Console.WriteLine(" - " + p.name); } } - } while (string.IsNullOrWhiteSpace(new_name) || + } while (string.IsNullOrWhiteSpace(new_name) || _current_settings.Projects.Any( p => p.name.Equals(new_name, StringComparison.OrdinalIgnoreCase))); return new_name; diff --git a/Humpback/Parts/SourceEditor.cs b/Humpback/Parts/SourceEditor.cs index 9242a06..c293d5f 100644 --- a/Humpback/Parts/SourceEditor.cs +++ b/Humpback/Parts/SourceEditor.cs @@ -1,59 +1,78 @@ -using System; +using Humpback.ConfigurationOptions; +using Humpback.Interfaces; +using Microsoft.Win32; +using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; -using Humpback.ConfigurationOptions; -using Humpback.Interfaces; -using Microsoft.Win32; -namespace Humpback.Parts { - public class SourceEditor : IHumpbackCommand { +namespace Humpback.Parts +{ + public class SourceEditor : IHumpbackCommand + { private IMigrationProvider _migration_provider; private Configuration _configuration; private MigrationViewer list_viewer; - public SourceEditor(Configuration configuration, IMigrationProvider migration_provider, MigrationViewer viewer) { + public SourceEditor(Configuration configuration, IMigrationProvider migration_provider, MigrationViewer viewer) + { _migration_provider = migration_provider; _configuration = configuration; list_viewer = viewer; } - public void Execute() { + public void Execute() + { int migration_id = 0; bool has_extra = _configuration.Extra.Any(); bool extra_is_int = has_extra && int.TryParse(_configuration.Extra.First(), out migration_id); bool migration_exists = extra_is_int && _migration_provider.GetMigrations().ContainsKey(migration_id); - if (migration_exists) { + if (migration_exists) + { var migration = _migration_provider.GetMigrationWithContents(migration_id); var file = new FileInfo(migration.Key); var fileName = file.FullName; dynamic up = Helpers.DeserializeMigration(migration.Value).up; - if (up.file != null) { // open sql file instead of json for sql file migrations + if (up.file != null) + { // open sql file instead of json for sql file migrations string path = up.file; path = path.Replace("..", "db"); - if(File.Exists(path)) { + if (File.Exists(path)) + { OpenFileInDefaultEditor(path); - } else { + } + else + { Console.WriteLine("Could not find sql file, opening migraion file."); OpenFileInDefaultEditor(fileName); } - } else { + } + else + { OpenFileInDefaultEditor(fileName); } - } else { + } + else + { Console.WriteLine("Please specify the number of a valid migration."); _configuration.Extra = new List(); list_viewer.Execute(); } } - public static void OpenFileInDefaultEditor(string fileName) { + public static void OpenFileInDefaultEditor(string fileName) + { Console.WriteLine("Opening {0} in the default editor.", fileName); - var text_editor = (string) Registry.GetValue(@"HKEY_CLASSES_ROOT\txtfile\shell\open\command\", "", "notepad.exe"); + var text_editor = (string)Registry.GetValue(@"HKEY_CLASSES_ROOT\txtfile\shell\open\command\", "", "notepad.exe"); + if (string.IsNullOrEmpty(text_editor) || !File.Exists(text_editor)) + { + string windowsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Windows); + text_editor = Path.Combine(windowsDirectory, "notepad.exe"); + } + text_editor = text_editor.Replace("\"%1\"", "").Trim(); System.Diagnostics.Process.Start(text_editor, fileName); } diff --git a/Humpback/Program.cs b/Humpback/Program.cs index dc03f0b..87f2036 100644 --- a/Humpback/Program.cs +++ b/Humpback/Program.cs @@ -1,15 +1,14 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using Humpback.ConfigurationOptions; +using Humpback.ConfigurationOptions; using Humpback.Interfaces; using Humpback.Parts; +using System; +using System.Collections.Generic; +using System.Diagnostics; -namespace Humpback { - class Program { +namespace Humpback +{ + class Program + { private static Configuration _configuration; private static IHumpbackCommand _humpback_command; private static IFileWriter _file_writer; @@ -18,64 +17,126 @@ class Program { private static IDatabaseProvider _database_provider; private static Settings _settings; - static int Main(string[] args) { - try { + static int Main(string[] args) + { + try + { _settings = Settings.Load(); _file_writer = new FileWriter(); _configuration = new Configuration(args); - _sql_formatter = new SQLServerFormatter(_configuration,_settings); + _sql_formatter = new SQLServerFormatter(_configuration, _settings); _database_provider = new SQLDatabaseProvider(_configuration, _settings, _sql_formatter); _migration_provider = new JsonFileMigrationProvider(_configuration, _settings, _database_provider); - - if (_configuration.WriteHelp) { + + if (_configuration.WriteHelp) + { _humpback_command = new Help(_configuration); - } else if (_configuration.Generate) { + } + else if (_configuration.Generate) + { Console.WriteLine("current project: " + _settings.CurrentProject); _settings.EnsureDirectories(); _humpback_command = new Generator(_configuration, _settings, _file_writer); - } else if (_configuration.List) { + } + else if (_configuration.List) + { _settings.EnsureDirectories(); _humpback_command = new MigrationViewer(_configuration, _migration_provider); - } else if (_configuration.File) { + } + else if (_configuration.File) + { _settings.EnsureDirectories(); _humpback_command = new SourceEditor(_configuration, _migration_provider, new MigrationViewer(_configuration, _migration_provider)); - } else if (_configuration.Migrate) { + } + else if (_configuration.Migrate) + { Console.WriteLine("current project: " + _settings.CurrentProject); _settings.EnsureDirectories(); _humpback_command = new Migrate(_configuration, _database_provider, _migration_provider); - } else if (_configuration.Sql) { + } + else if (_configuration.Sql) + { Console.WriteLine("current project: " + _settings.CurrentProject); _settings.EnsureDirectories(); _humpback_command = new GenerateSQL(_configuration, _settings, _sql_formatter, _file_writer, _migration_provider); - } else if(_configuration.Env) { + } + else if (_configuration.Env) + { _humpback_command = new SettingsActions(_configuration, _settings); } _humpback_command.Execute(); - } catch (Exception e) { + } + catch (Exception e) + { Console.WriteLine(e.Message); - if(e.InnerException != null) { - Console.WriteLine(e.InnerException.Message); - if (e.InnerException.InnerException != null) { - Console.WriteLine(e.InnerException.InnerException.Message); - } + var inner = e.InnerException; + while (inner != null) + { + Console.WriteLine(inner.Message); + inner = inner.InnerException; } - if(_configuration != null && _configuration.Verbose) { + + if (_configuration != null && _configuration.Verbose) + { Console.WriteLine(e.ToString()); } - if (Debugger.IsAttached) { + if (Debugger.IsAttached) + { Console.ReadLine(); } return -1; } - if(Debugger.IsAttached) { - Console.ReadLine(); + if (Debugger.IsAttached && Environment.UserInteractive) + { + string[] inputs = ParseUserString(Console.ReadLine()); + if (inputs.Length > 0) + { + Main(inputs); + } } + return 0; } + private static string[] ParseUserString(string userString) + { + if (string.IsNullOrWhiteSpace(userString)) + { + return new string[0]; + } + + int start = 0; + bool quote = false; + List inputs = new List(); + for (int i = 0; i < userString.Length; i++) + { + if (userString[i] == '"' || (!quote && userString[i] == ' ')) + { + if (i - start > 0) + { + inputs.Add(userString.Substring(start, i - start)); + } + + start = i + 1; + } + + if (userString[i] == '"') + { + quote = !quote; + } + } + + if (userString.Length - start > 0) + { + inputs.Add(userString.Substring(start, userString.Length - start)); + } + + return inputs.ToArray(); + } + } } diff --git a/Humpback/Properties/AssemblyInfo.cs b/Humpback/Properties/AssemblyInfo.cs index eaecb33..ebd73e9 100644 --- a/Humpback/Properties/AssemblyInfo.cs +++ b/Humpback/Properties/AssemblyInfo.cs @@ -1,8 +1,7 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Humpback")] @@ -14,24 +13,10 @@ [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("fbe207ef-760f-40d3-9821-604602de11de")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.2.0.0")] -[assembly: AssemblyFileVersion("0.2.0.0")] -[assembly: InternalsVisibleTo("Humpback.Tests")] \ No newline at end of file +[assembly: Guid("e7feaf88-d6c7-4804-9950-e5f21c1d5811")] \ No newline at end of file diff --git a/Humpback/Tools/DynamicJavascriptConverter.cs b/Humpback/Tools/DynamicJavascriptConverter.cs index 80332b8..e03a53b 100644 --- a/Humpback/Tools/DynamicJavascriptConverter.cs +++ b/Humpback/Tools/DynamicJavascriptConverter.cs @@ -10,56 +10,72 @@ // GOT THIS FROM STACK OVERFLOW. User: Drew Noakes // http://stackoverflow.com/questions/3142495/deserialize-json-into-c-dynamic-object/3806407#3806407 -namespace Humpback.Tools { - public sealed class DynamicJsonConverter : JavaScriptConverter { - public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) { +namespace Humpback.Tools +{ + public sealed class DynamicJsonConverter : JavaScriptConverter + { + public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) + { if (dictionary == null) throw new ArgumentNullException("dictionary"); return type == typeof(object) ? new DynamicJsonObject(dictionary) : null; } - public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) { + public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) + { throw new NotImplementedException(); } - public override IEnumerable SupportedTypes { + public override IEnumerable SupportedTypes + { get { return new ReadOnlyCollection(new List(new[] { typeof(object) })); } } #region Nested type: DynamicJsonObject - private sealed class DynamicJsonObject : DynamicObject { + private sealed class DynamicJsonObject : DynamicObject + { private readonly IDictionary _dictionary; - public DynamicJsonObject(IDictionary dictionary) { + public DynamicJsonObject(IDictionary dictionary) + { if (dictionary == null) throw new ArgumentNullException("dictionary"); _dictionary = dictionary; } - public override string ToString() { + public override string ToString() + { var sb = new StringBuilder("{"); ToString(sb); return sb.ToString(); } - private void ToString(StringBuilder sb) { + private void ToString(StringBuilder sb) + { var firstInDictionary = true; - foreach (var pair in _dictionary) { + foreach (var pair in _dictionary) + { if (!firstInDictionary) sb.Append(","); firstInDictionary = false; var value = pair.Value; var name = pair.Key; - if (value is string) { + if (value is string) + { sb.AppendFormat("{0}:\"{1}\"", name, value); - } else if (value is IDictionary) { + } + else if (value is IDictionary) + { new DynamicJsonObject((IDictionary)value).ToString(sb); - } else if (value is ArrayList) { + } + else if (value is ArrayList) + { sb.Append(name + ":["); var firstInArray = true; - foreach (var arrayValue in (ArrayList)value) { + foreach (var arrayValue in (ArrayList)value) + { if (!firstInArray) sb.Append(","); firstInArray = false; @@ -72,28 +88,34 @@ private void ToString(StringBuilder sb) { } sb.Append("]"); - } else { + } + else + { sb.AppendFormat("{0}:{1}", name, value); } } sb.Append("}"); } - public override bool TryGetMember(GetMemberBinder binder, out object result) { - if (!_dictionary.TryGetValue(binder.Name, out result)) { + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + if (!_dictionary.TryGetValue(binder.Name, out result)) + { // return null to avoid exception. caller can check for null this way... result = null; return true; } var dictionary = result as IDictionary; - if (dictionary != null) { + if (dictionary != null) + { result = new DynamicJsonObject(dictionary); return true; } var arrayList = result as ArrayList; - if (arrayList != null && arrayList.Count > 0) { + if (arrayList != null && arrayList.Count > 0) + { if (arrayList[0] is IDictionary) result = new List(arrayList.Cast>().Select(x => new DynamicJsonObject(x))); else diff --git a/Humpback/app.config b/Humpback/app.config index fa09898..e6369af 100644 --- a/Humpback/app.config +++ b/Humpback/app.config @@ -1,9 +1,118 @@ - + - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/Humpback/packages.config b/Humpback/packages.config new file mode 100644 index 0000000..9bd1454 --- /dev/null +++ b/Humpback/packages.config @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SharedVersionInfo.cs b/SharedVersionInfo.cs new file mode 100644 index 0000000..3403bee --- /dev/null +++ b/SharedVersionInfo.cs @@ -0,0 +1,14 @@ +using System.Reflection; + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.2.1.0")] +[assembly: AssemblyFileVersion("0.2.1.0")] \ No newline at end of file diff --git a/packages/repositories.config b/packages/repositories.config deleted file mode 100644 index e305eb2..0000000 --- a/packages/repositories.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/packages/xunit.1.9.0.1566/lib/xunit.dll b/packages/xunit.1.9.0.1566/lib/xunit.dll deleted file mode 100644 index 86168af..0000000 Binary files a/packages/xunit.1.9.0.1566/lib/xunit.dll and /dev/null differ diff --git a/packages/xunit.1.9.0.1566/lib/xunit.dll.tdnet b/packages/xunit.1.9.0.1566/lib/xunit.dll.tdnet deleted file mode 100644 index 4d8afc8..0000000 --- a/packages/xunit.1.9.0.1566/lib/xunit.dll.tdnet +++ /dev/null @@ -1,5 +0,0 @@ - - xUnit.net {0}.{1}.{2} build {3} - xunit.runner.tdnet.dll - Xunit.Runner.TdNet.TdNetRunner - \ No newline at end of file diff --git a/packages/xunit.1.9.0.1566/lib/xunit.runner.msbuild.dll b/packages/xunit.1.9.0.1566/lib/xunit.runner.msbuild.dll deleted file mode 100644 index ac2065d..0000000 Binary files a/packages/xunit.1.9.0.1566/lib/xunit.runner.msbuild.dll and /dev/null differ diff --git a/packages/xunit.1.9.0.1566/lib/xunit.runner.tdnet.dll b/packages/xunit.1.9.0.1566/lib/xunit.runner.tdnet.dll deleted file mode 100644 index f7d0639..0000000 Binary files a/packages/xunit.1.9.0.1566/lib/xunit.runner.tdnet.dll and /dev/null differ diff --git a/packages/xunit.1.9.0.1566/lib/xunit.runner.utility.dll b/packages/xunit.1.9.0.1566/lib/xunit.runner.utility.dll deleted file mode 100644 index cc1f21b..0000000 Binary files a/packages/xunit.1.9.0.1566/lib/xunit.runner.utility.dll and /dev/null differ diff --git a/packages/xunit.1.9.0.1566/lib/xunit.xml b/packages/xunit.1.9.0.1566/lib/xunit.xml deleted file mode 100644 index cfc4cb2..0000000 --- a/packages/xunit.1.9.0.1566/lib/xunit.xml +++ /dev/null @@ -1,2604 +0,0 @@ - - - - xunit - - - - - Contains various static methods that are used to verify that conditions are met during the - process of running tests. - - - - - Initializes a new instance of the class. - - - - - Verifies that a collection contains a given object. - - The type of the object to be verified - The object expected to be in the collection - The collection to be inspected - Thrown when the object is not present in the collection - - - - Verifies that a collection contains a given object, using an equality comparer. - - The type of the object to be verified - The object expected to be in the collection - The collection to be inspected - The comparer used to equate objects in the collection with the expected object - Thrown when the object is not present in the collection - - - - Verifies that a string contains a given sub-string, using the current culture. - - The sub-string expected to be in the string - The string to be inspected - Thrown when the sub-string is not present inside the string - - - - Verifies that a string contains a given sub-string, using the given comparison type. - - The sub-string expected to be in the string - The string to be inspected - The type of string comparison to perform - Thrown when the sub-string is not present inside the string - - - - Verifies that a collection does not contain a given object. - - The type of the object to be compared - The object that is expected not to be in the collection - The collection to be inspected - Thrown when the object is present inside the container - - - - Verifies that a collection does not contain a given object, using an equality comparer. - - The type of the object to be compared - The object that is expected not to be in the collection - The collection to be inspected - The comparer used to equate objects in the collection with the expected object - Thrown when the object is present inside the container - - - - Verifies that a string does not contain a given sub-string, using the current culture. - - The sub-string which is expected not to be in the string - The string to be inspected - Thrown when the sub-string is present inside the string - - - - Verifies that a string does not contain a given sub-string, using the current culture. - - The sub-string which is expected not to be in the string - The string to be inspected - The type of string comparison to perform - Thrown when the sub-string is present inside the given string - - - - Verifies that a block of code does not throw any exceptions. - - A delegate to the code to be tested - - - - Verifies that a collection is empty. - - The collection to be inspected - Thrown when the collection is null - Thrown when the collection is not empty - - - - Verifies that two objects are equal, using a default comparer. - - The type of the objects to be compared - The expected value - The value to be compared against - Thrown when the objects are not equal - - - - Verifies that two objects are equal, using a custom equatable comparer. - - The type of the objects to be compared - The expected value - The value to be compared against - The comparer used to compare the two objects - Thrown when the objects are not equal - - - - Verifies that two values are equal, within the number of decimal - places given by . - - The expected value - The value to be compared against - The number of decimal places (valid values: 0-15) - Thrown when the values are not equal - - - - Verifies that two values are equal, within the number of decimal - places given by . - - The expected value - The value to be compared against - The number of decimal places (valid values: 0-15) - Thrown when the values are not equal - - - - Verifies that two sequences are equivalent, using a default comparer. - - The type of the objects to be compared - The expected value - The value to be compared against - Thrown when the objects are not equal - - - - Verifies that two sequences are equivalent, using a custom equatable comparer. - - The type of the objects to be compared - The expected value - The value to be compared against - The comparer used to compare the two objects - Thrown when the objects are not equal - - - Do not call this method. - - - - Verifies that the condition is false. - - The condition to be tested - Thrown if the condition is not false - - - - Verifies that the condition is false. - - The condition to be tested - The message to show when the condition is not false - Thrown if the condition is not false - - - - Verifies that a value is within a given range. - - The type of the value to be compared - The actual value to be evaluated - The (inclusive) low value of the range - The (inclusive) high value of the range - Thrown when the value is not in the given range - - - - Verifies that a value is within a given range, using a comparer. - - The type of the value to be compared - The actual value to be evaluated - The (inclusive) low value of the range - The (inclusive) high value of the range - The comparer used to evaluate the value's range - Thrown when the value is not in the given range - - - - Verifies that an object is of the given type or a derived type. - - The type the object should be - The object to be evaluated - The object, casted to type T when successful - Thrown when the object is not the given type - - - - Verifies that an object is of the given type or a derived type. - - The type the object should be - The object to be evaluated - Thrown when the object is not the given type - - - - Verifies that an object is not exactly the given type. - - The type the object should not be - The object to be evaluated - Thrown when the object is the given type - - - - Verifies that an object is not exactly the given type. - - The type the object should not be - The object to be evaluated - Thrown when the object is the given type - - - - Verifies that an object is exactly the given type (and not a derived type). - - The type the object should be - The object to be evaluated - The object, casted to type T when successful - Thrown when the object is not the given type - - - - Verifies that an object is exactly the given type (and not a derived type). - - The type the object should be - The object to be evaluated - Thrown when the object is not the given type - - - - Verifies that a collection is not empty. - - The collection to be inspected - Thrown when a null collection is passed - Thrown when the collection is empty - - - - Verifies that two objects are not equal, using a default comparer. - - The type of the objects to be compared - The expected object - The actual object - Thrown when the objects are equal - - - - Verifies that two objects are not equal, using a custom equality comparer. - - The type of the objects to be compared - The expected object - The actual object - The comparer used to examine the objects - Thrown when the objects are equal - - - - Verifies that two sequences are not equivalent, using a default comparer. - - The type of the objects to be compared - The expected object - The actual object - Thrown when the objects are equal - - - - Verifies that two sequences are not equivalent, using a custom equality comparer. - - The type of the objects to be compared - The expected object - The actual object - The comparer used to compare the two objects - Thrown when the objects are equal - - - - Verifies that a value is not within a given range, using the default comparer. - - The type of the value to be compared - The actual value to be evaluated - The (inclusive) low value of the range - The (inclusive) high value of the range - Thrown when the value is in the given range - - - - Verifies that a value is not within a given range, using a comparer. - - The type of the value to be compared - The actual value to be evaluated - The (inclusive) low value of the range - The (inclusive) high value of the range - The comparer used to evaluate the value's range - Thrown when the value is in the given range - - - - Verifies that an object reference is not null. - - The object to be validated - Thrown when the object is not null - - - - Verifies that two objects are not the same instance. - - The expected object instance - The actual object instance - Thrown when the objects are the same instance - - - - Verifies that an object reference is null. - - The object to be inspected - Thrown when the object reference is not null - - - - Verifies that the provided object raised INotifyPropertyChanged.PropertyChanged - as a result of executing the given test code. - - The object which should raise the notification - The property name for which the notification should be raised - The test code which should cause the notification to be raised - Thrown when the notification is not raised - - - - Verifies that two objects are the same instance. - - The expected object instance - The actual object instance - Thrown when the objects are not the same instance - - - - Verifies that the given collection contains only a single - element of the given type. - - The collection. - The single item in the collection. - Thrown when the collection does not contain - exactly one element. - - - - Verifies that the given collection contains only a single - element of the given value. The collection may or may not - contain other values. - - The collection. - The value to find in the collection. - The single item in the collection. - Thrown when the collection does not contain - exactly one element. - - - - Verifies that the given collection contains only a single - element of the given type. - - The collection type. - The collection. - The single item in the collection. - Thrown when the collection does not contain - exactly one element. - - - - Verifies that the given collection contains only a single - element of the given type which matches the given predicate. The - collection may or may not contain other values which do not - match the given predicate. - - The collection type. - The collection. - The item matching predicate. - The single item in the filtered collection. - Thrown when the filtered collection does - not contain exactly one element. - - - - Verifies that the exact exception is thrown (and not a derived exception type). - - The type of the exception expected to be thrown - A delegate to the code to be tested - The exception that was thrown, when successful - Thrown when an exception was not thrown, or when an exception of the incorrect type is thrown - - - - Verifies that the exact exception is thrown (and not a derived exception type). - Generally used to test property accessors. - - The type of the exception expected to be thrown - A delegate to the code to be tested - The exception that was thrown, when successful - Thrown when an exception was not thrown, or when an exception of the incorrect type is thrown - - - - Verifies that the exact exception is thrown (and not a derived exception type). - - The type of the exception expected to be thrown - A delegate to the code to be tested - The exception that was thrown, when successful - Thrown when an exception was not thrown, or when an exception of the incorrect type is thrown - - - - Verifies that the exact exception is thrown (and not a derived exception type). - Generally used to test property accessors. - - The type of the exception expected to be thrown - A delegate to the code to be tested - The exception that was thrown, when successful - Thrown when an exception was not thrown, or when an exception of the incorrect type is thrown - - - - Verifies that an expression is true. - - The condition to be inspected - Thrown when the condition is false - - - - Verifies that an expression is true. - - The condition to be inspected - The message to be shown when the condition is false - Thrown when the condition is false - - - - Used by the PropertyChanged. - - - - - Used by the Throws and DoesNotThrow methods. - - - - - Used by the Throws and DoesNotThrow methods. - - - - - This command sets up the necessary trace listeners and standard - output/error listeners to capture Assert/Debug.Trace failures, - output to stdout/stderr, and Assert/Debug.Write text. It also - captures any exceptions that are thrown and packages them as - FailedResults, including the possibility that the configuration - file is messed up (which is exposed when we attempt to manipulate - the trace listener list). - - - - - Base class used by commands which delegate to inner commands. - - - - - Interface which represents the ability to invoke of a test method. - - - - - Executes the test method. - - The instance of the test class - Returns information about the test run - - - - Creates the start XML to be sent to the callback when the test is about to start - running. - - Return the of the start node, or null if the test - is known that it will not be running. - - - - Gets the display name of the test method. - - - - - Determines if the test runner infrastructure should create a new instance of the - test class before running the test. - - - - - Determines if the test should be limited to running a specific amount of time - before automatically failing. - - The timeout value, in milliseconds; if zero, the test will not have - a timeout. - - - - Creates a new instance of the class. - - The inner command to delegate to. - - - - - - - - - - - - - - - - - - - - - - Initializes a new instance of the - class. - - The command that will be wrapped. - The test method. - - - - - - - Represents an implementation of to be used with - tests which are decorated with the . - - - - - Represents an xUnit.net test command. - - - - - The method under test. - - - - - Initializes a new instance of the class. - - The method under test. - The display name of the test. - The timeout, in milliseconds. - - - - - - - - - - - - - Gets the name of the method under test. - - - - - - - - - - - Gets the name of the type under test. - - - - - Initializes a new instance of the class. - - The test method. - - - - - - - Base class for exceptions that have actual and expected values - - - - - The base assert exception class - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - The user message to be displayed - - - - Initializes a new instance of the class. - - The user message to be displayed - The inner exception - - - - Initializes a new instance of the class. - - The user message to be displayed - The stack trace to be displayed - - - - - - - Determines whether to exclude a line from the stack frame. By default, this method - removes all stack frames from methods beginning with Xunit.Assert or Xunit.Sdk. - - The stack frame to be filtered. - Return true to exclude the line from the stack frame; false, otherwise. - - - - Filters the stack trace to remove all lines that occur within the testing framework. - - The original stack trace - The filtered stack trace - - - - - - - Gets a string representation of the frames on the call stack at the time the current exception was thrown. - - A string that describes the contents of the call stack, with the most recent method call appearing first. - - - - Gets the user message - - - - - Creates a new instance of the class. - - The expected value - The actual value - The user message to be shown - - - - Creates a new instance of the class. - - The expected value - The actual value - The user message to be shown - Set to true to skip the check for difference position - - - - - - - - - - Gets the actual value. - - - - - Gets the expected value. - - - - - Gets a message that describes the current exception. Includes the expected and actual values. - - The error message that explains the reason for the exception, or an empty string(""). - 1 - - - - Exception thrown when a collection unexpectedly does not contain the expected value. - - - - - Creates a new instance of the class. - - The expected object value - - - - Creates a new instance of the class. - - The expected object value - The actual value - - - - - - - Exception to be thrown from when the number of - parameter values does not the test method signature. - - - - - - - - - - - Exception thrown when code unexpectedly fails change a property. - - - - - Creates a new instance of the class. Call this constructor - when no exception was thrown. - - The name of the property that was expected. - - - - - - - Exception thrown when the collection did not contain exactly one element. - - - - - Initializes a new instance of the class. - - The numbers of items in the collection. - - - - Initializes a new instance of the class. - - The numbers of items in the collection. - The object expected to be in the collection. - - - - - - - Internal class used for version-resilient test runners. DO NOT CALL DIRECTLY. - Version-resilient runners should link against xunit.runner.utility.dll and use - ExecutorWrapper instead. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Exception thrown when the value is unexpectedly not of the given type or a derived type. - - - - - Creates a new instance of the class. - - The expected type - The actual object value - - - - - - - Allows the user to record actions for a test. - - - - - Records any exception which is thrown by the given code. - - The code which may thrown an exception. - Returns the exception that was thrown by the code; null, otherwise. - - - - Records any exception which is thrown by the given code that has - a return value. Generally used for testing property accessors. - - The code which may thrown an exception. - Returns the exception that was thrown by the code; null, otherwise. - - - - Exception that is thrown when one or more exceptions are thrown from - the After method of a . - - - - - Initializes a new instance of the class. - - The exceptions. - - - - Initializes a new instance of the class. - - The exceptions. - - - - - - - - - - Gets the list of exceptions thrown in the After method. - - - - - Gets a message that describes the current exception. - - - - - Gets a string representation of the frames on the call stack at the time the current exception was thrown. - - - - - Implementation of which executes the - instances attached to a test method. - - - - - Initializes a new instance of the class. - - The inner command. - The method. - - - - Executes the test method. - - The instance of the test class - Returns information about the test run - - - - This class supports the xUnit.net infrastructure and is not intended to be used - directly from your code. - - - - - This API supports the xUnit.net infrastructure and is not intended to be used - directly from your code. - - - - - This API supports the xUnit.net infrastructure and is not intended to be used - directly from your code. - - - - - This API supports the xUnit.net infrastructure and is not intended to be used - directly from your code. - - - - - Guard class, used for guard clauses and argument validation - - - - - - - - - - - - - - Base class which contains XML manipulation helper methods - - - - - Interface that represents a single test result. - - - - - Converts the test result into XML that is consumed by the test runners. - - The parent node. - The newly created XML node. - - - - The amount of time spent in execution - - - - - Adds the test execution time to the XML node. - - The XML node. - - - - - - - - - - Utility methods for dealing with exceptions. - - - - - Gets the message for the exception, including any inner exception messages. - - The exception - The formatted message - - - - Gets the stack trace for the exception, including any inner exceptions. - - The exception - The formatted stack trace - - - - Rethrows an exception object without losing the existing stack trace information - - The exception to re-throw. - - For more information on this technique, see - http://www.dotnetjunkies.com/WebLog/chris.taylor/archive/2004/03/03/8353.aspx - - - - - A dictionary which contains multiple unique values for each key. - - The type of the key. - The type of the value. - - - - Adds the value for the given key. If the key does not exist in the - dictionary yet, it will add it. - - The key. - The value. - - - - Removes all keys and values from the dictionary. - - - - - Determines whether the dictionary contains to specified key and value. - - The key. - The value. - - - - Calls the delegate once for each key/value pair in the dictionary. - - - - - Removes the given key and all of its values. - - - - - Removes the given value from the given key. If this was the - last value for the key, then the key is removed as well. - - The key. - The value. - - - - Gets the values for the given key. - - - - - Gets the count of the keys in the dictionary. - - - - - Gets the keys. - - - - - - - - XML utility methods - - - - - Adds an attribute to an XML node. - - The XML node. - The attribute name. - The attribute value. - - - - Adds a child element to an XML node. - - The parent XML node. - The child element name. - The new child XML element. - - - - Exception that is thrown when a call to Debug.Assert() fails. - - - - - Creates a new instance of the class. - - The original assert message - - - - Creates a new instance of the class. - - The original assert message - The original assert detailed message - - - - - - - - - - Gets the original assert detailed message. - - - - - Gets the original assert message. - - - - - Gets a message that describes the current exception. - - - - - Exception thrown when a collection unexpectedly contains the expected value. - - - - - Creates a new instance of the class. - - The expected object value - - - - - - - Exception thrown when code unexpectedly throws an exception. - - - - - Creates a new instance of the class. - - Actual exception - - - - THIS CONSTRUCTOR IS FOR UNIT TESTING PURPOSES ONLY. - - - - - - - - - - - Gets a string representation of the frames on the call stack at the time the current exception was thrown. - - A string that describes the contents of the call stack, with the most recent method call appearing first. - - - - Exception thrown when a collection is unexpectedly not empty. - - - - - Creates a new instance of the class. - - - - - - - - Exception thrown when two values are unexpectedly not equal. - - - - - Creates a new instance of the class. - - The expected object value - The actual object value - - - - Creates a new instance of the class. - - The expected object value - The actual object value - Set to true to skip the check for difference position - - - - - - - Exception thrown when a value is unexpectedly true. - - - - - Creates a new instance of the class. - - The user message to be display, or null for the default message - - - - - - - Exception thrown when a value is unexpectedly not in the given range. - - - - - Creates a new instance of the class. - - The actual object value - The low value of the range - The high value of the range - - - - - - - - - - Gets the actual object value - - - - - Gets the high value of the range - - - - - Gets the low value of the range - - - - - Gets a message that describes the current exception. - - The error message that explains the reason for the exception, or an empty string(""). - - - - Exception thrown when the value is unexpectedly of the exact given type. - - - - - Creates a new instance of the class. - - The expected type - The actual object value - - - - - - - Exception thrown when the value is unexpectedly not of the exact given type. - - - - - Creates a new instance of the class. - - The expected type - The actual object value - - - - - - - Used to decorate xUnit.net test classes that utilize fixture classes. - An instance of the fixture data is initialized just before the first - test in the class is run, and if it implements IDisposable, is disposed - after the last test in the class is run. - - The type of the fixture - - - - Called on the test class just before each test method is run, - passing the fixture data so that it can be used for the test. - All test runs share the same instance of fixture data. - - The fixture data - - - - Exception thrown when a value is unexpectedly in the given range. - - - - - Creates a new instance of the class. - - The actual object value - The low value of the range - The high value of the range - - - - - - - - - - Gets the actual object value - - - - - Gets the high value of the range - - - - - Gets the low value of the range - - - - - Gets a message that describes the current exception. - - The error message that explains the reason for the exception, or an empty string(""). - - - - Base attribute which indicates a test method interception (allows code to be run before and - after the test is run). - - - - - This method is called after the test method is executed. - - The method under test - - - - This method is called before the test method is executed. - - The method under test - - - - - - - Exception thrown when a collection is unexpectedly empty. - - - - - Creates a new instance of the class. - - - - - - - - Exception thrown when two values are unexpectedly equal. - - - - - Creates a new instance of the class. - - - - - - - - Exception thrown when an object is unexpectedly null. - - - - - Creates a new instance of the class. - - - - - - - - Exception thrown when two values are unexpected the same instance. - - - - - Creates a new instance of the class. - - - - - - - - Exception thrown when an object reference is unexpectedly not null. - - - - - Creates a new instance of the class. - - - - - - - - - Command that automatically creates the instance of the test class - and disposes it (if it implements ). - - - - - Creates a new instance of the object. - - The command that is bring wrapped - The method under test - - - - Executes the test method. Creates a new instance of the class - under tests and passes it to the inner command. Also catches - any exceptions and converts them into s. - - The instance of the test class - Returns information about the test run - - - - Command used to wrap a which has associated - fixture data. - - - - - Creates a new instance of the class. - - The inner command - The fixtures to be set on the test class - - - - Sets the fixtures on the test class by calling SetFixture, then - calls the inner command. - - The instance of the test class - Returns information about the test run - - - - A timer class used to figure out how long tests take to run. On most .NET implementations - this will use the class because it's a high - resolution timer; however, on Silverlight/CoreCLR, it will use - (which will provide lower resolution results). - - - - - Creates a new instance of the class. - - - - - Starts timing. - - - - - Stops timing. - - - - - Gets how long the timer ran, in milliseconds. In order for this to be valid, - both and must have been called. - - - - - Attribute used to decorate a test method with arbitrary name/value pairs ("traits"). - - - - - Creates a new instance of the class. - - The trait name - The trait value - - - - Gets the trait name. - - - - - - - - Gets the trait value. - - - - - Runner that executes an synchronously. - - - - - Execute the . - - The test class command to execute - The methods to execute; if null or empty, all methods will be executed - The start run callback - The end run result callback - A with the results of the test run - - - - Factory for objects, based on the type under test. - - - - - Creates the test class command, which implements , for a given type. - - The type under test - The test class command, if the class is a test class; null, otherwise - - - - Creates the test class command, which implements , for a given type. - - The type under test - The test class command, if the class is a test class; null, otherwise - - - - Represents an xUnit.net test class - - - - - Interface which describes the ability to executes all the tests in a test class. - - - - - Allows the test class command to choose the next test to be run from the list of - tests that have not yet been run, thereby allowing it to choose the run order. - - The tests remaining to be run - The index of the test that should be run - - - - Execute actions to be run after all the test methods of this test class are run. - - Returns the thrown during execution, if any; null, otherwise - - - - Execute actions to be run before any of the test methods of this test class are run. - - Returns the thrown during execution, if any; null, otherwise - - - - Enumerates the test commands for a given test method in this test class. - - The method under test - The test commands for the given test method - - - - Enumerates the methods which are test methods in this test class. - - The test methods - - - - Determines if a given refers to a test method. - - The test method to validate - True if the method is a test method; false, otherwise - - - - Gets the object instance that is under test. May return null if you wish - the test framework to create a new object instance for each test method. - - - - - Gets or sets the type that is being tested - - - - - Creates a new instance of the class. - - - - - Creates a new instance of the class. - - The type under test - - - - Creates a new instance of the class. - - The type under test - - - - Chooses the next test to run, randomly, using the . - - The tests remaining to be run - The index of the test that should be run - - - - Execute actions to be run after all the test methods of this test class are run. - - Returns the thrown during execution, if any; null, otherwise - - - - Execute actions to be run before any of the test methods of this test class are run. - - Returns the thrown during execution, if any; null, otherwise - - - - Enumerates the test commands for a given test method in this test class. - - The method under test - The test commands for the given test method - - - - Enumerates the methods which are test methods in this test class. - - The test methods - - - - Determines if a given refers to a test method. - - The test method to validate - True if the method is a test method; false, otherwise - - - - Gets the object instance that is under test. May return null if you wish - the test framework to create a new object instance for each test method. - - - - - Gets or sets the randomizer used to determine the order in which tests are run. - - - - - Sets the type that is being tested - - - - - Implementation of that represents a skipped test. - - - - - Creates a new instance of the class. - - The method that is being skipped - The display name for the test. If null, the fully qualified - type name is used. - The reason the test was skipped. - - - - - - - - - - Gets the skip reason. - - - - - - - - Factory for creating objects. - - - - - Make instances of objects for the given class and method. - - The class command - The method under test - The set of objects - - - - A command wrapper which times the running of a command. - - - - - Creates a new instance of the class. - - The command that will be timed. - - - - Executes the inner test method, gathering the amount of time it takes to run. - - Returns information about the test run - - - - Wraps a command which should fail if it runs longer than the given timeout value. - - - - - Creates a new instance of the class. - - The command to be run - The timout, in milliseconds - The method under test - - - - Executes the test method, failing if it takes too long. - - Returns information about the test run - - - - - - - Attributes used to decorate a test fixture that is run with an alternate test runner. - The test runner must implement the interface. - - - - - Creates a new instance of the class. - - The class which implements ITestClassCommand and acts as the runner - for the test fixture. - - - - Gets the test class command. - - - - - Exception thrown when two object references are unexpectedly not the same instance. - - - - - Creates a new instance of the class. - - The expected object reference - The actual object reference - - - - - - - Contains the test results from an assembly. - - - - - Contains multiple test results, representing them as a composite test result. - - - - - Adds a test result to the composite test result list. - - - - - - Gets the test results. - - - - - Creates a new instance of the class. - - The filename of the assembly - - - - Creates a new instance of the class. - - The filename of the assembly - The configuration filename - - - - Converts the test result into XML that is consumed by the test runners. - - The parent node. - The newly created XML node. - - - - Gets the fully qualified filename of the configuration file. - - - - - Gets the directory where the assembly resides. - - - - - Gets the number of failed results. - - - - - Gets the fully qualified filename of the assembly. - - - - - Gets the number of passed results. - - - - - Gets the number of skipped results. - - - - - Contains the test results from a test class. - - - - - Creates a new instance of the class. - - The type under test - - - - Creates a new instance of the class. - - The simple name of the type under test - The fully qualified name of the type under test - The namespace of the type under test - - - - Sets the exception thrown by the test fixture. - - The thrown exception - - - - Converts the test result into XML that is consumed by the test runners. - - The parent node. - The newly created XML node. - - - - Gets the fully qualified test fixture exception type, when an exception has occurred. - - - - - Gets the number of tests which failed. - - - - - Gets the fully qualified name of the type under test. - - - - - Gets the test fixture exception message, when an exception has occurred. - - - - - Gets the simple name of the type under test. - - - - - Gets the namespace of the type under test. - - - - - Gets the number of tests which passed. - - - - - Gets the number of tests which were skipped. - - - - - Gets the test fixture exception stack trace, when an exception has occurred. - - - - - Represents a failed test result. - - - - - Represents the results from running a test method - - - - - Initializes a new instance of the class. The traits for - the test method are discovered using reflection. - - The method under test. - The display name for the test. If null, the fully qualified - type name is used. - - - - Initializes a new instance of the class. - - The name of the method under test. - The type of the method under test. - The display name for the test. If null, the fully qualified - type name is used. - The traits. - - - - Converts the test result into XML that is consumed by the test runners. - - The parent node. - The newly created XML node. - - - - Gets or sets the display name of the method under test. This is the value that's shown - during failures and in the resulting output XML. - - - - - Gets the name of the method under test. - - - - - Gets or sets the standard output/standard error from the test that was captured - while the test was running. - - - - - Gets the traits attached to the test method. - - - - - Gets the name of the type under test. - - - - - Creates a new instance of the class. - - The method under test - The exception throw by the test - The display name for the test. If null, the fully qualified - type name is used. - - - - Creates a new instance of the class. - - The name of the method under test - The name of the type under test - The display name of the test - The custom properties attached to the test method - The full type name of the exception throw - The exception message - The exception stack trace - - - - Converts the test result into XML that is consumed by the test runners. - - The parent node. - The newly created XML node. - - - - Gets the exception type thrown by the test method. - - - - - Gets the exception message thrown by the test method. - - - - - Gets the stack trace of the exception thrown by the test method. - - - - - Represents a passing test result. - - - - - Create a new instance of the class. - - The method under test - The display name for the test. If null, the fully qualified - type name is used. - - - - Create a new instance of the class. - - The name of the method under test - The name of the type under test - The display name for the test. If null, the fully qualified - type name is used. - The custom properties attached to the test method - - - - Converts the test result into XML that is consumed by the test runners. - - The parent node. - The newly created XML node. - - - - Represents a skipped test result. - - - - - Creates a new instance of the class. Uses reflection to discover - the skip reason. - - The method under test - The display name for the test. If null, the fully qualified - type name is used. - The reason the test was skipped. - - - - Creates a new instance of the class. - - The name of the method under test - The name of the type under test - The display name for the test. If null, the fully qualified - type name is used. - The traits attached to the method under test - The skip reason - - - - Converts the test result into XML that is consumed by the test runners. - - The parent node. - The newly created XML node. - - - - Gets the skip reason. - - - - - Represents information about an attribute. - - - - - Gets the instance of the attribute, if available. - - The type of the attribute - The instance of the attribute, if available. - - - - Gets an initialized property value of the attribute. - - The type of the property - The name of the property - The property value - - - - Represents information about a method. - - - - - Creates an instance of the type where this test method was found. If using - reflection, this should be the ReflectedType. - - A new instance of the type. - - - - Gets all the custom attributes for the method that are of the given type. - - The type of the attribute - The matching attributes that decorate the method - - - - Determines if the method has at least one instance of the given attribute type. - - The type of the attribute - True if the method has at least one instance of the given attribute type; false, otherwise - - - - Invokes the test on the given class, with the given parameters. - - The instance of the test class (may be null if - the test method is static). - The parameters to be passed to the test method. - - - - Gets a value which represents the class that this method was - reflected from (i.e., equivalent to MethodInfo.ReflectedType) - - - - - Gets a value indicating whether the method is abstract. - - - - - Gets a value indicating whether the method is static. - - - - - Gets the underlying for the method, if available. - - - - - Gets the name of the method. - - - - - Gets the fully qualified type name of the return type. - - - - - Gets the fully qualified type name of the type that this method belongs to. If - using reflection, this should be the ReflectedType. - - - - - Represents information about a type. - - - - - Gets all the custom attributes for the type that are of the given attribute type. - - The type of the attribute - The matching attributes that decorate the type - - - - Gets a test method by name. - - The name of the method - The method, if it exists; null, otherwise. - - - - Gets all the methods - - - - - - Determines if the type has at least one instance of the given attribute type. - - The type of the attribute - True if the type has at least one instance of the given attribute type; false, otherwise - - - - Determines if the type implements the given interface. - - The type of the interface - True if the type implements the given interface; false, otherwise - - - - Gets a value indicating whether the type is abstract. - - - - - Gets a value indicating whether the type is sealed. - - - - - Gets the underlying object, if available. - - - - - Utility class which inspects methods for test information - - - - - Gets the display name. - - The method to be inspected - The display name - - - - Gets the skip reason from a test method. - - The method to be inspected - The skip reason - - - - Gets the test commands for a test method. - - The method to be inspected - The objects for the test method - - - - Gets the timeout value for a test method. - - The method to be inspected - The timeout, in milliseconds - - - - Gets the traits on a test method. - - The method to be inspected - A dictionary of the traits - - - - Determines whether a test method has a timeout. - - The method to be inspected - True if the method has a timeout; false, otherwise - - - - Determines whether a test method has traits. - - The method to be inspected - True if the method has traits; false, otherwise - - - - Determines whether a test method should be skipped. - - The method to be inspected - True if the method should be skipped; false, otherwise - - - - Determines whether a method is a test method. A test method must be decorated - with the (or derived class) and must not be abstract. - - The method to be inspected - True if the method is a test method; false, otherwise - - - - Wrapper to implement and using reflection. - - - - - Converts an into an using reflection. - - - - - - - Converts a into an using reflection. - - The method to wrap - The wrapper - - - - Converts a into an using reflection. - - The type to wrap - The wrapper - - - - Utility class which inspects types for test information - - - - - Determines if a type contains any test methods - - The type to be inspected - True if the class contains any test methods; false, otherwise - - - - Retrieves the type to run the test class with from the , if present. - - The type to be inspected - The type of the test class runner, if present; null, otherwise - - - - Retrieves a list of the test methods from the test class. - - The type to be inspected - The test methods - - - - Determines if the test class has a applied to it. - - The type to be inspected - True if the test class has a run with attribute; false, otherwise - - - - Determines if the type implements . - - The type to be inspected - True if the type implements ; false, otherwise - - - - Determines whether the specified type is abstract. - - The type. - - true if the specified type is abstract; otherwise, false. - - - - - Determines whether the specified type is static. - - The type. - - true if the specified type is static; otherwise, false. - - - - - Determines if a class is a test class. - - The type to be inspected - True if the type is a test class; false, otherwise - - - - Attribute that is applied to a method to indicate that it is a fact that should be run - by the test runner. It can also be extended to support a customized definition of a - test method. - - - - - Creates instances of which represent individual intended - invocations of the test method. - - The method under test - An enumerator through the desired test method invocations - - - - Enumerates the test commands represented by this test method. Derived classes should - override this method to return instances of , one per execution - of a test method. - - The test method - The test commands which will execute the test runs for the given method - - - - Gets the name of the test to be used when the test is skipped. Defaults to - null, which will cause the fully qualified test name to be used. - - - - - Obsolete. Please use the property instead. - - - - - Marks the test so that it will not be run, and gets or sets the skip reason - - - - - Marks the test as failing if it does not finish running within the given time - period, in milliseconds; set to 0 or less to indicate the method has no timeout - - - - - Exception thrown when code unexpectedly fails to throw an exception. - - - - - Creates a new instance of the class. Call this constructor - when no exception was thrown. - - The type of the exception that was expected - - - - Creates a new instance of the class. Call this constructor - when an exception of the wrong type was thrown. - - The type of the exception that was expected - The actual exception that was thrown - - - - - - - THIS CONSTRUCTOR IS FOR UNIT TESTING PURPOSES ONLY. - - - - - - - - Gets a string representation of the frames on the call stack at the time the current exception was thrown. - - A string that describes the contents of the call stack, with the most recent method call appearing first. - - - - Exception thrown when a test method exceeds the given timeout value - - - - - Creates a new instance of the class. - - The timeout value, in milliseconds - - - - - - - Exception thrown when a value is unexpectedly false. - - - - - Creates a new instance of the class. - - The user message to be displayed, or null for the default message - - - - - - diff --git a/packages/xunit.1.9.0.1566/xunit.1.9.0.1566.nupkg b/packages/xunit.1.9.0.1566/xunit.1.9.0.1566.nupkg deleted file mode 100644 index 6fa9304..0000000 Binary files a/packages/xunit.1.9.0.1566/xunit.1.9.0.1566.nupkg and /dev/null differ