Example #1
0
        public override void Execute(HortonOptions options)
        {
            if (!options.Unattend)
            {
                Program.PrintLine("=== Add Migration ===");
                Program.PrintLine();
            }

            var migrationName = "";
            if (options.ExtraArguments.Length > 0)
            {
                migrationName = options.ExtraArguments[0];
            }
            while (string.IsNullOrEmpty(migrationName))
            {
                if (options.Unattend)
                {
                    Program.PrintErrorLine("Migration name is required while running in Unattend mode. Specificy Migration name as the last argument.");
                    Environment.Exit(1);
                }
                Program.PrintLine("Please enter a name for the migration and press return.");
                migrationName = Console.ReadLine();
                Program.PrintLine();
            }

            migrationName = migrationName.Replace(" ", "_");

            var loader = new FileLoader(options.MigrationsDirectoryPath);
            loader.LoadAllFiles();
            var lastMigrationScript = loader.Files.OfType<MigrationScript>().OrderBy(x => x.SerialNumber).Last();

            var newSerialNumber = lastMigrationScript.SerialNumber + 1;
            var serialNumberDigits = lastMigrationScript.FileName.IndexOf('_');
            var newMigrationDirectory = Path.GetDirectoryName(lastMigrationScript.FilePath);
            var migrationFileName = newSerialNumber.ToString().PadLeft(serialNumberDigits, '0') + "_" + migrationName + ".sql";
            var newMigrationFullFilePath = Path.Combine(newMigrationDirectory, migrationFileName);

            Program.Print("Writing migration: ");
            Program.PrintLine(ConsoleColor.DarkGreen, newMigrationFullFilePath);

            File.WriteAllText(newMigrationFullFilePath, "");

            if (!options.Unattend)
            {
                System.Diagnostics.Process.Start(newMigrationFullFilePath);
                Program.PrintLine();
                Program.PrintLine("Finished.");
            }
        }
Example #2
0
        public override void Execute(HortonOptions options)
        {
            using (var schemaInfo = new SchemaInfo(options))
            {
                schemaInfo.InitializeTable();

                Program.PrintLine("=== History ===");
                Program.PrintLine();
                Program.PrintLine("Timestamp (UTC)        | File Name            | User");
                Program.PrintLine("---------------------------------------------------------------------");
                foreach (var item in schemaInfo.AppliedMigrations)
                {
                    Program.PrintLine($"{item.AppliedUTC.ToString("yyyy-MM-dd HH:mm:ss.ff")} | {TrimOrPad(item.FileName, 20)} | {TrimOrPad(item.SystemUser, 20)}");
                }
            }
        }
Example #3
0
        public override void Execute(HortonOptions options)
        {
            using (var schemaInfo = new SchemaInfo(options))
            {
                schemaInfo.InitializeTable();

                var loader = new FileLoader(options.MigrationsDirectoryPath);
                loader.LoadAllFiles();

                Program.PrintLine("=== Info ===");
                Program.PrintLine();
                Program.PrintLine("The following scripts will execute...");

                bool willExecuteMigrations = true;

                foreach (var file in loader.Files)
                {
                    var existingRecord = schemaInfo.AppliedMigrations.SingleOrDefault(x => x.FileNameMD5Hash == file.FileNameHash);
                    if (existingRecord != null)
                    {
                        if (file.ContentMatches(existingRecord.ContentSHA1Hash))
                        {
                            continue;
                        }
                        if (file.ConflictOnContent)
                        {
                            Program.PrintLine(ConsoleColor.Red, $"\nCONFLICT: The script \"{file.FileName}\" has changed since it was applied on \"{existingRecord.AppliedUTC.ToString("yyyy-MM-dd HH:mm:ss.ff")}\".");
                            willExecuteMigrations = false;
                            continue;
                        }
                    }
                    Program.PrintLine(ConsoleColor.DarkGreen, $"\n\"{file.FileName}\" will execute on UPDATE.");
                }

                if (!willExecuteMigrations)
                {
                    Program.PrintLine(ConsoleColor.Red, $"\nWARNING! Migrations will not execute until conflicts are resolved.");
                    Environment.Exit(1);
                }

                Program.PrintLine();
                Program.PrintLine("Finished.");
            }
        }
Example #4
0
        public override void Execute(HortonOptions options)
        {
            using (var schemaInfo = new SchemaInfo(options))
            {
                schemaInfo.InitializeTable();

                var loader = new FileLoader(options.MigrationsDirectoryPath);
                loader.LoadAllFiles();

                Program.PrintLine("=== Sync ===");
                Program.PrintLine();
                Program.PrintLine("Synchronizing conflicting scripts...");

                foreach (var file in loader.Files)
                {
                    var existingRecord = schemaInfo.AppliedMigrations.SingleOrDefault(x => x.FileNameMD5Hash == file.FileNameHash);
                    if (existingRecord != null)
                    {
                        if (!file.ContentMatches(existingRecord.ContentSHA1Hash))
                        {
                            Program.Print(ConsoleColor.Red, $"\n\"{file.FileName}\" has changed since it was applied on \"{existingRecord.AppliedUTC.ToString("yyyy-MM-dd HH:mm:ss.ff")}\" and will be updated.");
                            Program.Print(ConsoleColor.Red, " Type 'Y' to Continue.");
                            Program.PrintLine();
                            var c = Console.ReadKey();
                            if (c.KeyChar == 'y' || c.KeyChar == 'Y')
                            {
                                Program.PrintLine($"\nUpdating \"{file.FileName}\" with hash \"{file.ContentSHA1Hash}\"");
                                schemaInfo.ResyncMigration(file);
                            }
                            else
                            {
                                Program.PrintLine("\nAborting...");
                                Environment.Exit(1);
                            }
                        }
                    }
                }

                Program.PrintLine();
                Program.PrintLine("Finished.");
            }
        }
Example #5
0
        private static void MainInternal(string[] args)
        {
            var options = new HortonOptions();
            bool showHelp = false;
            bool printVersion = false;

            var p = new OptionSet()
            {
                { "m|migrations=", "path to migration scripts.\n(leave blank for current directory)", v => options.MigrationsDirectoryPath = v },
                { "s|server=", "server hostname.\n(leave blank for \"localhost\")", v => options.ServerHostname = v },
                { "d|database=", "database name.\n(leave blank to look for \"database.name\")", v => options.DatabaseName = v },
                { "u|username="******"username of the database connection.\n(leave blank for integrated security)", v => options.Username = v },
                { "p|password="******"password of the database connection.\n(required if username is provided)", v => options.Password = v },
                { "c|connectionString=", "ADO.NET connection string.\n(optional, overrides other parameters)", v => options.ConnectionString = v },
                { "U|UNATTEND", "Surpress user acknowledgement during\nexecution.", v => options.Unattend = v != null },
                { "v|version",  "Print version number and exit.", v => printVersion = v != null },
                { "h|help|?",  "show help message and exit.", v => showHelp = v != null },
            };

            if (args.Length == 0)
            {
                showHelp = true;
            }

            List<string> extra;
            try
            {
                extra = p.Parse(args);
            }
            catch (OptionException e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `horton.exe --help' for more information.");
                return;
            }

            if (!options.Unattend)
            {
                Console.WriteLine("Horton. The simple database migration utility.");
            }

            if (showHelp)
            {
                ShowHelp(p);
                return;
            }

            if (printVersion)
            {
                Console.WriteLine("Version: " + typeof(Program).Assembly.GetName().Version.ToString());
                return;
            }

            options.Command = HortonCommands.TryParseCommand(extra.FirstOrDefault() ?? "");
            options.ExtraArguments = extra.Skip(1).ToArray();

            string firstValidationMessage = "";
            if (!options.AssertValid(out firstValidationMessage))
            {
                Console.WriteLine(firstValidationMessage);
                Console.WriteLine("Try `horton.exe --help' for more information.");
                Environment.Exit(1);
            }

            options.Command.Execute(options);
        }