diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index 49af5b9b3a..5a16be9422 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -35,13 +35,6 @@ namespace Umbraco.Core.Components public static MapperCollectionBuilder Mappers(this Composition composition) => composition.Container.GetInstance(); - /// - /// Gets the migrations collection builder. - /// - /// The composition. - public static MigrationCollectionBuilder Migrations(this Composition composition) - => composition.Container.GetInstance(); - /// /// Gets the package actions collection builder. /// @@ -84,6 +77,13 @@ namespace Umbraco.Core.Components internal static ValidatorCollectionBuilder Validators(this Composition composition) => composition.Container.GetInstance(); + /// + /// Gets the post-migrations collection builder. + /// + /// The composition. + internal static PostMigrationCollectionBuilder PostMigrations(this Composition composition) + => composition.Container.GetInstance(); + #endregion #region Singleton diff --git a/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs index 3b51a380c7..c9a536f0ce 100644 --- a/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs +++ b/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; namespace Umbraco.Core.Composing.CompositionRoots { @@ -25,6 +26,7 @@ namespace Umbraco.Core.Composing.CompositionRoots container.RegisterSingleton(); // register the services + container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); diff --git a/src/Umbraco.Core/Constants-System.cs b/src/Umbraco.Core/Constants-System.cs index 69a3bbc9bd..9438e4590e 100644 --- a/src/Umbraco.Core/Constants-System.cs +++ b/src/Umbraco.Core/Constants-System.cs @@ -23,7 +23,7 @@ public const int RecycleBinMedia = -21; public const string UmbracoConnectionName = "umbracoDbDSN"; - public const string UmbracoMigrationName = "Umbraco"; + public const string UmbracoUpgraderName = "Umbraco.Core"; } } } diff --git a/src/Umbraco.Core/CoreRuntime.cs b/src/Umbraco.Core/CoreRuntime.cs index 96b614048a..32942b1ff5 100644 --- a/src/Umbraco.Core/CoreRuntime.cs +++ b/src/Umbraco.Core/CoreRuntime.cs @@ -335,7 +335,7 @@ namespace Umbraco.Core var sql = databaseFactory.SqlContext.Sql() .Select() .From() - .Where(x => x.Name.InvariantEquals(Constants.System.UmbracoMigrationName) && x.Version == codeVersionString); + .Where(x => x.Name.InvariantEquals(Constants.System.UmbracoUpgraderName) && x.Version == codeVersionString); return database.FirstOrDefault(sql) != null; } } diff --git a/src/Umbraco.Core/CoreRuntimeComponent.cs b/src/Umbraco.Core/CoreRuntimeComponent.cs index 81505c66d2..5352a66ca5 100644 --- a/src/Umbraco.Core/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/CoreRuntimeComponent.cs @@ -105,9 +105,6 @@ namespace Umbraco.Core composition.Container.RegisterCollectionBuilder() .Add(f => f.GetInstance().GetPackageActions()); - composition.Container.RegisterCollectionBuilder() - .Add(factory => factory.GetInstance().GetTypes()); - // need to filter out the ones we dont want!! fixme - what does that mean? composition.Container.RegisterCollectionBuilder() .Append(factory => factory.GetInstance().GetTypes()); @@ -121,6 +118,9 @@ namespace Umbraco.Core composition.Container.RegisterCollectionBuilder() .Append(); + composition.Container.RegisterCollectionBuilder() + .Add(factory => factory.GetInstance().GetTypes()); + // by default, register a noop factory composition.Container.RegisterSingleton(); } diff --git a/src/Umbraco.Core/Migrations/IMigration.cs b/src/Umbraco.Core/Migrations/IMigration.cs index e50a295a72..53b7874b3a 100644 --- a/src/Umbraco.Core/Migrations/IMigration.cs +++ b/src/Umbraco.Core/Migrations/IMigration.cs @@ -3,11 +3,10 @@ namespace Umbraco.Core.Migrations { /// - /// Marker interface for database migrations + /// Represents a migration. /// public interface IMigration : IDiscoverable { - void Up(); - void Down(); + void Migrate(); } } diff --git a/src/Umbraco.Core/Migrations/IMigrationBuilder.cs b/src/Umbraco.Core/Migrations/IMigrationBuilder.cs new file mode 100644 index 0000000000..3d78d825a7 --- /dev/null +++ b/src/Umbraco.Core/Migrations/IMigrationBuilder.cs @@ -0,0 +1,9 @@ +using System; + +namespace Umbraco.Core.Migrations +{ + public interface IMigrationBuilder + { + IMigration Build(Type migrationType, IMigrationContext context); + } +} diff --git a/src/Umbraco.Core/Migrations/IMigrationCollectionBuilder.cs b/src/Umbraco.Core/Migrations/IMigrationCollectionBuilder.cs deleted file mode 100644 index 98cf1374dd..0000000000 --- a/src/Umbraco.Core/Migrations/IMigrationCollectionBuilder.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Umbraco.Core.Migrations -{ - // exists so the builder can be mocked in tests - public interface IMigrationCollectionBuilder - { - /// - /// Gets all migration types. - /// - IEnumerable MigrationTypes { get; } - - /// - /// Instanciates a migration. - /// - IMigration Instanciate(Type migrationType, IMigrationContext context); - } -} diff --git a/src/Umbraco.Core/Migrations/IPostMigration.cs b/src/Umbraco.Core/Migrations/IPostMigration.cs new file mode 100644 index 0000000000..827a09e882 --- /dev/null +++ b/src/Umbraco.Core/Migrations/IPostMigration.cs @@ -0,0 +1,11 @@ +using Semver; +using Umbraco.Core.Logging; +using Umbraco.Core.Scoping; + +namespace Umbraco.Core.Migrations +{ + public interface IPostMigration + { + void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger); + } +} diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs index 12931b608c..f09fecbbef 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs @@ -4,11 +4,11 @@ using System.Data.SqlServerCe; using System.IO; using System.Linq; using System.Xml.Linq; -using Semver; using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; @@ -24,18 +24,22 @@ namespace Umbraco.Core.Migrations.Install private readonly IUmbracoDatabaseFactory _databaseFactory; private readonly IScopeProvider _scopeProvider; private readonly IRuntimeState _runtime; - private readonly IMigrationEntryService _migrationEntryService; + private readonly IMigrationBuilder _migrationBuilder; + private readonly IKeyValueService _keyValueService; + private readonly PostMigrationCollection _postMigrations; private readonly ILogger _logger; private DatabaseSchemaResult _databaseSchemaValidationResult; - public DatabaseBuilder(IScopeProvider scopeProvider, IUmbracoDatabaseFactory databaseFactory, IRuntimeState runtime, IMigrationEntryService migrationEntryService, ILogger logger) + public DatabaseBuilder(IScopeProvider scopeProvider, IUmbracoDatabaseFactory databaseFactory, IRuntimeState runtime, ILogger logger, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations) { _scopeProvider = scopeProvider; _databaseFactory = databaseFactory; _runtime = runtime; - _migrationEntryService = migrationEntryService; _logger = logger; + _migrationBuilder = migrationBuilder; + _keyValueService = keyValueService; + _postMigrations = postMigrations; } #region Status @@ -495,18 +499,8 @@ namespace Umbraco.Core.Migrations.Install } } - internal Result UpgradeSchemaAndData(IMigrationEntryService migrationEntryService, MigrationCollectionBuilder builder) - { - using (var scope = _scopeProvider.CreateScope()) - { - var result = UpgradeSchemaAndData(scope, migrationEntryService, builder); - scope.Complete(); - return result; - } - } - // This assumes all of the previous checks are done! - private Result UpgradeSchemaAndData(IScope scope, IMigrationEntryService migrationEntryService, MigrationCollectionBuilder builder) + internal Result UpgradeSchemaAndData() { try { @@ -518,54 +512,56 @@ namespace Umbraco.Core.Migrations.Install _logger.Info("Database upgrade started"); - var database = scope.Database; + //var database = scope.Database; //var supportsCaseInsensitiveQueries = SqlSyntax.SupportsCaseInsensitiveQueries(database); var message = GetResultMessageForMySql(); - var schemaResult = ValidateDatabaseSchema(); + // fixme - remove this code + //var schemaResult = ValidateDatabaseSchema(); + // + //var installedSchemaVersion = new SemVersion(schemaResult.DetermineInstalledVersion()); + //var installedMigrationVersion = schemaResult.DetermineInstalledVersionByMigrations(migrationEntryService); + //var targetVersion = UmbracoVersion.Current; + // + ////In some cases - like upgrading from 7.2.6 -> 7.3, there will be no migration information in the database and therefore it will + //// return a version of 0.0.0 and we don't necessarily want to run all migrations from 0 -> 7.3, so we'll just ensure that the + //// migrations are run for the target version + //if (installedMigrationVersion == new SemVersion(new Version(0, 0, 0)) && installedSchemaVersion > new SemVersion(new Version(0, 0, 0))) + //{ + // //set the installedMigrationVersion to be one less than the target so the latest migrations are guaranteed to execute + // installedMigrationVersion = new SemVersion(targetVersion.SubtractRevision()); + //} + // + ////Figure out what our current installed version is. If the web.config doesn't have a version listed, then we'll use the minimum + //// version detected between the schema installed and the migrations listed in the migration table. + //// If there is a version in the web.config, we'll take the minimum between the listed migration in the db and what + //// is declared in the web.config. + // + //var currentInstalledVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) + // //Take the minimum version between the detected schema version and the installed migration version + // ? new[] { installedSchemaVersion, installedMigrationVersion }.Min() + // //Take the minimum version between the installed migration version and the version specified in the config + // : new[] { SemVersion.Parse(GlobalSettings.ConfigurationStatus), installedMigrationVersion }.Min(); + // + ////Ok, another edge case here. If the current version is a pre-release, + //// then we want to ensure all migrations for the current release are executed. + //if (currentInstalledVersion.Prerelease.IsNullOrWhiteSpace() == false) + //{ + // currentInstalledVersion = new SemVersion(currentInstalledVersion.GetVersion().SubtractRevision()); + //} - var installedSchemaVersion = new SemVersion(schemaResult.DetermineInstalledVersion()); - var installedMigrationVersion = schemaResult.DetermineInstalledVersionByMigrations(migrationEntryService); - var targetVersion = UmbracoVersion.Current; + // upgrade + var upgrader = new UmbracoUpgrader(_scopeProvider, _migrationBuilder, _keyValueService, _postMigrations, _logger); + upgrader.Execute(); - //In some cases - like upgrading from 7.2.6 -> 7.3, there will be no migration information in the database and therefore it will - // return a version of 0.0.0 and we don't necessarily want to run all migrations from 0 -> 7.3, so we'll just ensure that the - // migrations are run for the target version - if (installedMigrationVersion == new SemVersion(new Version(0, 0, 0)) && installedSchemaVersion > new SemVersion(new Version(0, 0, 0))) - { - //set the installedMigrationVersion to be one less than the target so the latest migrations are guaranteed to execute - installedMigrationVersion = new SemVersion(targetVersion.SubtractRevision()); - } - - //Figure out what our current installed version is. If the web.config doesn't have a version listed, then we'll use the minimum - // version detected between the schema installed and the migrations listed in the migration table. - // If there is a version in the web.config, we'll take the minimum between the listed migration in the db and what - // is declared in the web.config. - - var currentInstalledVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) - //Take the minimum version between the detected schema version and the installed migration version - ? new[] { installedSchemaVersion, installedMigrationVersion }.Min() - //Take the minimum version between the installed migration version and the version specified in the config - : new[] { SemVersion.Parse(GlobalSettings.ConfigurationStatus), installedMigrationVersion }.Min(); - - //Ok, another edge case here. If the current version is a pre-release, - // then we want to ensure all migrations for the current release are executed. - if (currentInstalledVersion.Prerelease.IsNullOrWhiteSpace() == false) - { - currentInstalledVersion = new SemVersion(currentInstalledVersion.GetVersion().SubtractRevision()); - } - - //DO the upgrade! - - var runner = new MigrationRunner(_scopeProvider, builder, migrationEntryService, _logger, currentInstalledVersion, UmbracoVersion.SemanticVersion, Constants.System.UmbracoMigrationName); - - var upgraded = runner.Execute(/*upgrade:true*/); - - if (upgraded == false) - { - throw new ApplicationException("Upgrading failed, either an error occurred during the upgrade process or an event canceled the upgrade process, see log for full details"); - } + // fixme remove this code + //var runner = new MigrationRunner(_scopeProvider, builder, migrationEntryService, _logger, currentInstalledVersion, UmbracoVersion.SemanticVersion, Constants.System.UmbracoMigrationName); + //var upgraded = runner.Execute(/*upgrade:true*/); + //if (upgraded == false) + //{ + // throw new ApplicationException("Upgrading failed, either an error occurred during the upgrade process or an event canceled the upgrade process, see log for full details"); + //} message = message + "

Upgrade completed!

"; diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs index fde99b392d..780df8c205 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs @@ -306,7 +306,7 @@ namespace Umbraco.Core.Migrations.Install var dto = new MigrationDto { Id = 1, - Name = Constants.System.UmbracoMigrationName, + Name = Constants.System.UmbracoUpgraderName, Version = UmbracoVersion.SemanticVersion.ToString(), CreateDate = DateTime.Now }; diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs index 5f29a20ec8..7274fb5c56 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs @@ -50,7 +50,7 @@ namespace Umbraco.Core.Migrations.Install if (ValidTables.Any(x => x.InvariantEquals("umbracoMigration"))) { - var allMigrations = migrationEntryService.GetAll(Constants.System.UmbracoMigrationName); + var allMigrations = migrationEntryService.GetAll(Constants.System.UmbracoUpgraderName); mostrecent = allMigrations.OrderByDescending(x => x.Version).Select(x => x.Version).FirstOrDefault(); } diff --git a/src/Umbraco.Core/Migrations/MigrationAttribute.cs b/src/Umbraco.Core/Migrations/MigrationAttribute.cs deleted file mode 100644 index 77b9968308..0000000000 --- a/src/Umbraco.Core/Migrations/MigrationAttribute.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; - -namespace Umbraco.Core.Migrations -{ - /// - /// Represents the Migration attribute, which is used to mark classes as - /// database migrations with Up/Down methods for pushing changes UP or pulling them DOWN. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public sealed class MigrationAttribute : Attribute - { - public MigrationAttribute(string targetVersion, int sortOrder, string product) - { - TargetVersion = new Version(targetVersion); - SortOrder = sortOrder; - ProductName = product; - } - - public MigrationAttribute(string minimumCurrentVersion, string targetVersion, int sortOrder, string product) - { - TargetVersion = new Version(targetVersion); - MinimumCurrentVersion = new Version(minimumCurrentVersion); - SortOrder = sortOrder; - ProductName = product; - } - - /// - /// Gets the minimum current version for which this migration is allowed to execute - /// - public Version MinimumCurrentVersion { get; private set; } - - /// - /// Gets the target version of this migration. - /// - public Version TargetVersion { get; private set; } - - /// - /// Gets or sets the sort order, which is the order this migration will be run in. - /// - public int SortOrder { get; private set; } - - /// - /// Gets or sets the name of the product, which this migration belongs to. - /// - public string ProductName { get; set; } - } -} diff --git a/src/Umbraco.Core/Migrations/MigrationBase.cs b/src/Umbraco.Core/Migrations/MigrationBase.cs index 5e89182121..d2420fdd33 100644 --- a/src/Umbraco.Core/Migrations/MigrationBase.cs +++ b/src/Umbraco.Core/Migrations/MigrationBase.cs @@ -63,16 +63,7 @@ namespace Umbraco.Core.Migrations protected Sql Sql(string sql, params object[] args) => Context.SqlContext.Sql(sql, args); /// - public virtual void Up() - { - throw new NotSupportedException("This migration does not implement the \"up\" operation."); - } - - /// - public virtual void Down() - { - throw new NotSupportedException("This migration does not implement the \"down\" operation."); - } + public abstract void Migrate(); /// /// Builds an Alter expression. diff --git a/src/Umbraco.Core/Migrations/MigrationBuilder.cs b/src/Umbraco.Core/Migrations/MigrationBuilder.cs new file mode 100644 index 0000000000..3d8c88c771 --- /dev/null +++ b/src/Umbraco.Core/Migrations/MigrationBuilder.cs @@ -0,0 +1,36 @@ +using System; +using LightInject; + +namespace Umbraco.Core.Migrations +{ + public class MigrationBuilder : IMigrationBuilder + { + private readonly IServiceContainer _container; + + public MigrationBuilder(IServiceContainer container) + { + _container = container; + + // because the builder should be "per container" this ctor should run only once per container. + // + // note: constructor dependencies do NOT work with lifetimes other than transient + // see https://github.com/seesharper/LightInject/issues/294 + // + // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is + // the container, 'info' describes the ctor argument, and 'args' contains the args that + // were passed to GetInstance() - use first arg if it is the right type. + // + // for IMigrationContext + container.RegisterConstructorDependency((factory, info, args) => args.Length > 0 ? args[0] as IMigrationContext : null); + } + + public IMigration Build(Type migrationType, IMigrationContext context) + { + // LightInject .Create() is a shortcut for .Register() + .GetInstance() + // but it does not support parameters, so we do it ourselves here + + _container.Register(migrationType); + return (IMigration) _container.GetInstance(migrationType, new object[] { context }); + } + } +} diff --git a/src/Umbraco.Core/Migrations/MigrationCollection.cs b/src/Umbraco.Core/Migrations/MigrationCollection.cs deleted file mode 100644 index bbb3c2f817..0000000000 --- a/src/Umbraco.Core/Migrations/MigrationCollection.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Composing; - -namespace Umbraco.Core.Migrations -{ - public class MigrationCollection : BuilderCollectionBase - { - public MigrationCollection(IEnumerable items) - : base(items) - { } - } -} diff --git a/src/Umbraco.Core/Migrations/MigrationCollectionBuilder.cs b/src/Umbraco.Core/Migrations/MigrationCollectionBuilder.cs deleted file mode 100644 index a29d5e32a6..0000000000 --- a/src/Umbraco.Core/Migrations/MigrationCollectionBuilder.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using LightInject; -using Umbraco.Core.Composing; - -namespace Umbraco.Core.Migrations -{ - public class MigrationCollectionBuilder : LazyCollectionBuilderBase, IMigrationCollectionBuilder - { - public MigrationCollectionBuilder(IServiceContainer container) - : base(container) - { - // because collection builders are "per container" this ctor should run only once per container. - // - // note: constructor dependencies do NOT work with lifetimes other than transient - // see https://github.com/seesharper/LightInject/issues/294 - // - // resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is - // the container, 'info' describes the ctor argument, and 'args' contains the args that - // were passed to GetInstance() - use first arg if it is the right type. - // - // for IMigrationContext - container.RegisterConstructorDependency((factory, info, args) => args.Length > 0 ? args[0] as IMigrationContext : null); - } - - protected override void Initialize() - { - // nothing - do not register the collection - } - - protected override MigrationCollectionBuilder This => this; - - // this is *not* needed since we do not register the collection - // however, keep it here to be absolutely explicit about it - protected override ILifetime CollectionLifetime { get; } = null; // transient - - public IEnumerable MigrationTypes => GetTypes(); - - public IMigration Instanciate(Type migrationType, IMigrationContext context) - { - return (IMigration) Container.GetInstance(migrationType, new [] { context }); - } - } -} diff --git a/src/Umbraco.Core/Migrations/MigrationPlan.cs b/src/Umbraco.Core/Migrations/MigrationPlan.cs new file mode 100644 index 0000000000..d9f5845311 --- /dev/null +++ b/src/Umbraco.Core/Migrations/MigrationPlan.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Exceptions; +using Umbraco.Core.Logging; +using Umbraco.Core.Scoping; + +namespace Umbraco.Core.Migrations +{ + public class MigrationPlan + { + private readonly string _name; + private readonly IScopeProvider _scopeProvider; + private readonly IMigrationBuilder _migrationBuilder; + private readonly ILogger _logger; + private readonly Dictionary _transitions = new Dictionary(); + + private string _prevState; + + public MigrationPlan(string name, IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, ILogger logger) + { + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name)); + _name = name; + _scopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider)); + _migrationBuilder = migrationBuilder ?? throw new ArgumentNullException(nameof(migrationBuilder)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public MigrationPlan Add(string sourceState, string targetState) + => Add(sourceState, targetState); + + public MigrationPlan Add(string sourceState, string targetState) + where TMigration : IMigration + => Add(sourceState, targetState, typeof(TMigration)); + + public MigrationPlan Add(string sourceState, string targetState, Type migration) + { + if (sourceState == null) throw new ArgumentNullException(nameof(sourceState)); + if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentNullOrEmptyException(nameof(targetState)); + if (sourceState == targetState) throw new ArgumentException("Source and target state cannot be identical."); + if (migration == null) throw new ArgumentNullException(nameof(migration)); + if (!migration.Implements()) throw new ArgumentException($"Type {migration.Name} does not implement IMigration.", nameof(migration)); + + sourceState = sourceState.Trim(); + targetState = targetState.Trim(); + + // throw if we already have a transition for that state which is not null, + // null is used to keep track of the last step of the chain + if (_transitions.ContainsKey(sourceState) && _transitions[sourceState] != null) + throw new InvalidOperationException($"A transition from state \"{sourceState}\" has already been defined."); + + // register the transition + _transitions[sourceState] = new Transition + { + SourceState = sourceState, + TargetState = targetState, + MigrationType = migration + }; + + // register the target state if we don't know it already + // this is how we keep track of the final state - because + // transitions could be defined in any order, that might + // be overriden afterwards. + if (!_transitions.ContainsKey(targetState)) + _transitions.Add(targetState, null); + + _prevState = targetState; + + return this; + } + + public MigrationPlan Chain(string targetState) + => Chain(targetState); + + public MigrationPlan Chain(string targetState) + where TMigration : IMigration + => Chain(targetState, typeof(TMigration)); + + public MigrationPlan Chain(string targetState, Type migration) + => Add(_prevState, targetState, migration); + + public MigrationPlan From(string sourceState) + { + _prevState = sourceState ?? throw new ArgumentNullException(nameof(sourceState)); + return this; + } + + // internal for tests + internal void Validate() + { + // quick check for dead ends - a dead end is a transition that has a target state + // that is not null and does not match any source state. such a target state has + // been registered as a source state with a null transition. so there should be only + // one. + string finalState = null; + foreach (var kvp in _transitions.Where(x => x.Value == null)) + { + if (finalState == null) + finalState = kvp.Key; + else + throw new Exception("Multiple final states have been detected."); + } + + // now check for loops + var verified = new List(); + foreach (var transition in _transitions.Values) + { + if (transition == null || verified.Contains(transition.SourceState)) continue; + + var visited = new List { transition.SourceState }; + var nextTransition = _transitions[transition.TargetState]; + while (nextTransition != null && !verified.Contains(nextTransition.SourceState)) + { + if (visited.Contains(nextTransition.SourceState)) + throw new Exception("A loop has been detected."); + visited.Add(nextTransition.SourceState); + nextTransition = _transitions[nextTransition.TargetState]; + } + verified.AddRange(visited); + } + } + + public string Execute(IScope scope, string fromState) + { + Validate(); + + _logger.Info("Starting \"{0}\"...", () => _name); + var origState = fromState; //GetState(); + var info = "At " + (string.IsNullOrWhiteSpace(origState) ? "origin" : ("\"" + origState + "\"")) + "."; + info = info.Replace("{", "{{").Replace("}", "}}"); // stupid log4net + _logger.Info(info); + + if (!_transitions.TryGetValue(origState, out var transition)) + throw new Exception($"Unknown state \"{origState}\"."); + + var context = new MigrationContext(scope.Database, _logger); + + while (transition != null) + { + var migration = _migrationBuilder.Build(transition.MigrationType, context); + migration.Migrate(); + + var nextState = transition.TargetState; + origState = nextState; + + // ReSharper disable once AccessToModifiedClosure + _logger.Info("At \"{0}\".", () => origState); + + if (!_transitions.TryGetValue(origState, out transition)) + throw new Exception($"Unknown state \"{origState}\"."); + } + + _logger.Info("Done (pending scope completion)."); + + // fixme - what about post-migrations? + return origState; + } + + private class Transition + { + public string SourceState { get; set; } + public string TargetState { get; set; } + public Type MigrationType { get; set; } + } + } +} diff --git a/src/Umbraco.Core/Migrations/MigrationRunner.cs b/src/Umbraco.Core/Migrations/MigrationRunner.cs deleted file mode 100644 index 756a860109..0000000000 --- a/src/Umbraco.Core/Migrations/MigrationRunner.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Semver; -using Umbraco.Core.Events; -using Umbraco.Core.Exceptions; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; -using Umbraco.Core.Scoping; -using Umbraco.Core.Services; - -namespace Umbraco.Core.Migrations -{ - /// - /// Represents the Migration Runner, which is used to apply migrations to - /// the umbraco database. - /// - public class MigrationRunner - { - private readonly IScopeProvider _scopeProvider; - private readonly IMigrationCollectionBuilder _migrationBuilder; - private readonly ILogger _logger; - - private readonly Type[] _migrationTypes; - private readonly IMigrationEntryService _migrationEntryService; - private readonly SemVersion _currentVersion; - private readonly SemVersion _targetVersion; - private readonly string _productName; - - private MigrationRunner(IScopeProvider scopeProvider, IMigrationCollectionBuilder migrationBuilder, IMigrationEntryService migrationEntryService, ILogger logger, SemVersion currentVersion, SemVersion targetVersion, string productName) - { - if (string.IsNullOrWhiteSpace(productName)) throw new ArgumentNullOrEmptyException(nameof(productName)); - - _scopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider)); - _migrationBuilder = migrationBuilder ?? throw new ArgumentNullException(nameof(migrationBuilder)); - _migrationEntryService = migrationEntryService ?? throw new ArgumentNullException(nameof(migrationEntryService)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _currentVersion = currentVersion ?? throw new ArgumentNullException(nameof(currentVersion)); - _targetVersion = targetVersion ?? throw new ArgumentNullException(nameof(targetVersion)); - - _productName = productName; - } - - public MigrationRunner(IScopeProvider scopeProvider, IMigrationCollectionBuilder migrationBuilder, IMigrationEntryService migrationEntryService, ILogger logger, SemVersion currentVersion, SemVersion targetVersion, string productName, params Type[] migrations) - : this(scopeProvider, migrationBuilder, migrationEntryService, logger, currentVersion, targetVersion, productName) - { - _migrationTypes = migrations == null || migrations.Length == 0 ? null : migrations; - } - - /// - /// Executes migrations. - /// - public bool Execute(bool upgrade = true) - { - _logger.Info("Initializing database migrations"); - - // get migrations to execute - var mt = GetMigrationTypes(); - mt = upgrade - ? OrderedUpgradeMigrations(mt) - : OrderedDowngradeMigrations(mt); - var migrationTypes = mt.ToList(); - - if (Migrating.IsRaisedEventCancelled(new MigrationEventArgs(migrationTypes, _currentVersion, _targetVersion, _productName, true), this)) - { - _logger.Warn("Migration was cancelled by an event"); - return false; - } - - try - { - using (var scope = _scopeProvider.CreateScope()) - { - var context = new MigrationContext(scope.Database, _logger); - var migrations = migrationTypes.Select(x => _migrationBuilder.Instanciate(x, context)); - ExecuteMigrations(migrations, upgrade); - - // note: event is NOT dispatched but raised immediately - // so the transaction has not completed yet and context.Database is available - Migrated.RaiseEvent(new MigrationEventArgs(migrationTypes, context, _currentVersion, _targetVersion, _productName, false), this); - - scope.Complete(); - } - } - catch (Exception ex) - { - // the scope did not complete, and the transaction rolled back - BUT MySql does not support transactional - // schema changes (http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html) - so the database is now - // in an unknown state - raise a warning - if (_scopeProvider.SqlContext.DatabaseType.IsMySql()) - { - throw new DataLossException( - "An error occurred running a schema migration but the changes could not be rolled back. Error: " + ex.Message - + ". In some cases, it may be required that the database be restored to it's original state before running this upgrade process again.", - ex); - } - - // else just rethrow - throw; - } - - return true; - } - - // gets all migration types - private IEnumerable GetMigrationTypes() - { - return _migrationTypes ?? _migrationBuilder.MigrationTypes; - } - - // filters and order migrations for upgrade, based upon _currentVersion and _targetVersion - // internal for tests - internal IEnumerable OrderedUpgradeMigrations(IEnumerable migrations) - { - // get the version instance to compare with the migrations as a normal c# Version object with only 3 parts - var targetVersionToCompare = _targetVersion.GetVersion(3); - var currentVersionToCompare = _currentVersion.GetVersion(3); - - return migrations - .Select(x => new { migrationType = x, migrationAttributes = x.GetCustomAttributes(false) }) - .SelectMany(x => x.migrationAttributes, (xx, migrationAttribute) => new { xx.migrationType, migrationAttribute }) - .Where(x => - x.migrationAttribute != null - && x.migrationAttribute.TargetVersion > currentVersionToCompare - && x.migrationAttribute.TargetVersion <= targetVersionToCompare - && x.migrationAttribute.ProductName == _productName - && (x.migrationAttribute.MinimumCurrentVersion == null || currentVersionToCompare >= x.migrationAttribute.MinimumCurrentVersion)) - .OrderBy(x => x.migrationAttribute.TargetVersion) - .ThenBy(x => x.migrationAttribute.SortOrder) - .Select(x => x.migrationType).Distinct(); - } - - // filters and order migrations for downgrade, based upon _currentVersion and _targetVersion - // internal for tests - internal IEnumerable OrderedDowngradeMigrations(IEnumerable migrations) - { - // get the version instance to compare with the migrations as a normal c# Version object with only 3 parts - var targetVersionToCompare = _targetVersion.GetVersion(3); - var currentVersionToCompare = _currentVersion.GetVersion(3); - - return migrations - .Select(x => new { migrationType = x, migrationAttributes = x.GetCustomAttributes(false) }) - .SelectMany(x => x.migrationAttributes, (xx, migrationAttribute) => new { xx.migrationType, migrationAttribute }) - .Where(x => - x.migrationAttribute != null - && x.migrationAttribute.TargetVersion > currentVersionToCompare - && x.migrationAttribute.TargetVersion <= targetVersionToCompare - && x.migrationAttribute.ProductName == _productName - && (x.migrationAttribute.MinimumCurrentVersion == null || currentVersionToCompare >= x.migrationAttribute.MinimumCurrentVersion)) - .OrderBy(x => x.migrationAttribute.TargetVersion) - .ThenByDescending(x => x.migrationAttribute.SortOrder) - .Select(x => x.migrationType).Distinct(); - } - - // executes migrations - // within a transaction - internal void ExecuteMigrations(IEnumerable migrations, bool upgrade = true) - { - foreach (var migration in migrations) - { - if (upgrade) migration.Up(); - else migration.Down(); - } - - var exists = _migrationEntryService.FindEntry(_productName, _targetVersion); // fixme refactor - if (exists == null) - _migrationEntryService.CreateEntry(_productName, _targetVersion); - } - - /// - /// Occurs before migrations run. - /// - public static event TypedEventHandler Migrating; - - /// - /// Occurs after migrations run. - /// - public static event TypedEventHandler Migrated; - } -} diff --git a/src/Umbraco.Core/Migrations/NopMigration.cs b/src/Umbraco.Core/Migrations/NopMigration.cs new file mode 100644 index 0000000000..8a584bc6ef --- /dev/null +++ b/src/Umbraco.Core/Migrations/NopMigration.cs @@ -0,0 +1,10 @@ +namespace Umbraco.Core.Migrations +{ + public class NopMigration : IMigration + { + public void Migrate() + { + // nop + } + } +} diff --git a/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollection.cs b/src/Umbraco.Core/Migrations/PostMigrationCollection.cs similarity index 86% rename from src/Umbraco.Web/Strategies/Migrations/PostMigrationCollection.cs rename to src/Umbraco.Core/Migrations/PostMigrationCollection.cs index 6ad883a3f8..488bdfd72d 100644 --- a/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollection.cs +++ b/src/Umbraco.Core/Migrations/PostMigrationCollection.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Umbraco.Core.Composing; -namespace Umbraco.Web.Strategies.Migrations +namespace Umbraco.Core.Migrations { public class PostMigrationCollection : BuilderCollectionBase { diff --git a/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollectionBuilder.cs b/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs similarity index 91% rename from src/Umbraco.Web/Strategies/Migrations/PostMigrationCollectionBuilder.cs rename to src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs index a450de70a2..63cdaf4454 100644 --- a/src/Umbraco.Web/Strategies/Migrations/PostMigrationCollectionBuilder.cs +++ b/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs @@ -1,7 +1,7 @@ using LightInject; using Umbraco.Core.Composing; -namespace Umbraco.Web.Strategies.Migrations +namespace Umbraco.Core.Migrations { public class PostMigrationCollectionBuilder : LazyCollectionBuilderBase { diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddContentNuTable.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddContentNuTable.cs index 02ceb636ec..49573295b7 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddContentNuTable.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddContentNuTable.cs @@ -4,14 +4,13 @@ using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight { - [Migration("8.0.0", 100, Constants.System.UmbracoMigrationName)] class AddContentNuTable : MigrationBase { public AddContentNuTable(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray(); if (tables.InvariantContains("cmsContentNu")) return; @@ -39,8 +38,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight .OnUpdate(Rule.None) .Do(); } - - public override void Down() - { } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddLockObjects.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddLockObjects.cs index 334d62aa4f..4ae7304076 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddLockObjects.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddLockObjects.cs @@ -2,14 +2,13 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight { - [Migration("8.0.0", 101, Constants.System.UmbracoMigrationName)] public class AddLockObjects : MigrationBase { public AddLockObjects(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { // some may already exist, just ensure everything we need is here EnsureLockObject(Constants.Locks.Servers, "Servers"); @@ -22,11 +21,6 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight EnsureLockObject(Constants.Locks.Domains, "Domains"); } - public override void Down() - { - // not implemented - } - private void EnsureLockObject(int id, string name) { var db = Database; diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddLockTable.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddLockTable.cs index 6a29b72543..968bff934d 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddLockTable.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddLockTable.cs @@ -2,14 +2,13 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight { - [Migration("8.0.0", 100, Constants.System.UmbracoMigrationName)] public class AddLockTable : MigrationBase { public AddLockTable(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray(); if (tables.InvariantContains("umbracoLock") == false) @@ -21,10 +20,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight .Do(); } } - - public override void Down() - { - // not implemented - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/RefactorXmlColumns.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/RefactorXmlColumns.cs index f0d1bf57c1..ed4d936e9c 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/RefactorXmlColumns.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/RefactorXmlColumns.cs @@ -5,14 +5,13 @@ using Umbraco.Core.Persistence; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight { - [Migration("8.0.0", 100, Constants.System.UmbracoMigrationName)] public class RefactorXmlColumns : MigrationBase { public RefactorXmlColumns(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { if (ColumnExists("cmsContentXml", "Rv") == false) Alter.Table("cmsContentXml").AddColumn("Rv").AsInt64().NotNullable().WithDefaultValue(0).Do(); @@ -68,16 +67,6 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight .Do(); } - public override void Down() - { - throw new DataLossException("Downgrading is not supported."); - - //if (Exists("cmsContentXml", "Rv")) - // Delete.Column("Rv").FromTable("cmsContentXml"); - //if (Exists("cmsPreviewXml", "Rv")) - // Delete.Column("Rv").FromTable("cmsContentXml"); - } - private bool ColumnExists(string tableName, string columnName) { // that's ok even on MySql diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/Seven1.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/Seven1.cs deleted file mode 100644 index e2764114a9..0000000000 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/Seven1.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveFive; -using Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveZero; -using Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero; -using Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero; - -namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight -{ - // catch-up with 7 migrations - // fixme - this is temp and should be removed! - - [Migration("8.0.0", 100, Constants.System.UmbracoMigrationName)] - public class Seven1 : MigrationBase - { - public Seven1(IMigrationContext context) - : base(context) - { } - - public override void Up() - { - var migrations = new MigrationBase[] - { - // 7.5.0 - new RemoveStylesheetDataAndTablesAgain(Context), - new TargetVersionSevenFiveZero.UpdateUniqueIndexOnPropertyData(Context), - - // 7.5.5 - new UpdateAllowedMediaTypesAtRoot(Context), - - // 7.6.0 - new AddIndexesToUmbracoRelationTables(Context), - new AddIndexToCmsMemberLoginName(Context), - new AddIndexToUmbracoNodePath(Context), - new AddMacroUniqueIdColumn(Context), - new AddRelationTypeUniqueIdColumn(Context), - new NormalizeTemplateGuids(Context), - new ReduceLoginNameColumnsSize(Context), - new TargetVersionSevenSixZero.UpdateUniqueIndexOnPropertyData(Context), - new RemoveUmbracoDeployTables(Context), - - // 7.7.0 - new AddIndexToDictionaryKeyColumn(Context), - new AddUserGroupTables(Context), - new AddUserStartNodeTable(Context), - new EnsureContentTemplatePermissions(Context), - new ReduceDictionaryKeyColumnsSize(Context), - new UpdateUserTables(Context) - }; - - foreach (var migration in migrations) - migration.Up(); - } - } -} diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/VariantsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/VariantsMigration.cs index 3a6f04245b..16dbff645a 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/VariantsMigration.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/VariantsMigration.cs @@ -9,7 +9,6 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight { - [Migration("8.0.0", 1000, Constants.System.UmbracoMigrationName)] public class VariantsMigration : MigrationBase { public VariantsMigration(IMigrationContext context) @@ -20,7 +19,7 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight // do NOT use Rename.Column as it's borked on SQLCE - use ReplaceColumn instead // not sure it all runs on MySql, needs to test - public override void Up() + public override void Migrate() { // delete *all* keys and indexes - because of FKs Delete.KeysAndIndexes().Do(); diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/AddLockObjects.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/AddLockObjects.cs deleted file mode 100644 index c638cd5ceb..0000000000 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/AddLockObjects.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveFive -{ - [Migration("7.5.5", 101, Constants.System.UmbracoMigrationName)] - public class AddLockObjects : MigrationBase - { - public AddLockObjects(IMigrationContext context) - : base(context) - { } - - public override void Up() - { - EnsureLockObject(Constants.Locks.Servers, "Servers"); - } - - public override void Down() - { - // not implemented - } - - private void EnsureLockObject(int id, string name) - { - var db = Database; - var exists = db.Exists(id); - if (exists) return; - // be safe: delete old umbracoNode lock objects if any - db.Execute("DELETE FROM umbracoNode WHERE id=@id;", new { id }); - // then create umbracoLock object - db.Execute("INSERT umbracoLock (id, name, value) VALUES (@id, @name, 1);", new { id, name }); - } - } -} diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/AddLockTable.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/AddLockTable.cs deleted file mode 100644 index 66b0b2f6e3..0000000000 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/AddLockTable.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Linq; - -namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveFive -{ - [Migration("7.5.5", 100, Constants.System.UmbracoMigrationName)] - public class AddLockTable : MigrationBase - { - public AddLockTable(IMigrationContext context) - : base(context) - { } - - public override void Up() - { - var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray(); - if (tables.InvariantContains("umbracoLock") == false) - { - Create.Table("umbracoLock") - .WithColumn("id").AsInt32().PrimaryKey("PK_umbracoLock") - .WithColumn("value").AsInt32().NotNullable() - .WithColumn("name").AsString(64).NotNullable() - .Do(); - } - } - - public override void Down() - { - // not implemented - } - } -} diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/UpdateAllowedMediaTypesAtRoot.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/UpdateAllowedMediaTypesAtRoot.cs index a9ec92939e..6d688284b0 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/UpdateAllowedMediaTypesAtRoot.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveFive/UpdateAllowedMediaTypesAtRoot.cs @@ -3,19 +3,15 @@ /// /// See: http://issues.umbraco.org/issue/U4-4196 /// - [Migration("7.5.5", 1, Constants.System.UmbracoMigrationName)] public class UpdateAllowedMediaTypesAtRoot : MigrationBase { public UpdateAllowedMediaTypesAtRoot(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { Database.Execute("UPDATE cmsContentType SET allowAtRoot = 1 WHERE nodeId = 1032 OR nodeId = 1033"); } - - public override void Down() - { } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddRedirectUrlTable.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/AddRedirectUrlTable.cs similarity index 89% rename from src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddRedirectUrlTable.cs rename to src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/AddRedirectUrlTable.cs index 52ac789493..bd3f5e1b28 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionEight/AddRedirectUrlTable.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/AddRedirectUrlTable.cs @@ -1,15 +1,14 @@ using System.Linq; -namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight +namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveZero { - [Migration("8.0.0", 100, Constants.System.UmbracoMigrationName)] public class AddRedirectUrlTable : MigrationBase { public AddRedirectUrlTable(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var database = Database; var umbracoRedirectUrlTableName = "umbracoRedirectUrl"; @@ -47,8 +46,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionEight .ToTable("umbracoNode").PrimaryColumn("uniqueID") .Do(); } - - public override void Down() - { } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/RemoveStylesheetDataAndTablesAgain.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/RemoveStylesheetDataAndTablesAgain.cs index 8d358c066d..162d27fbaf 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/RemoveStylesheetDataAndTablesAgain.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/RemoveStylesheetDataAndTablesAgain.cs @@ -5,7 +5,6 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveZero /// /// This is here to re-remove these tables, we dropped them in 7.3 but new installs created them again so we're going to re-drop them /// - [Migration("7.5.0", 1, Constants.System.UmbracoMigrationName)] public class RemoveStylesheetDataAndTablesAgain : MigrationBase { public RemoveStylesheetDataAndTablesAgain(IMigrationContext context) @@ -13,7 +12,7 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveZero { } - public override void Up() + public override void Migrate() { //Clear all stylesheet data if the tables exist var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray(); @@ -32,8 +31,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveZero Delete.Table("cmsStylesheet").Do(); } } - - public override void Down() - { } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/UpdateUniqueIndexOnPropertyData.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/UpdateUniqueIndexOnPropertyData.cs index d08da84ac4..834d7b45b7 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/UpdateUniqueIndexOnPropertyData.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenFiveZero/UpdateUniqueIndexOnPropertyData.cs @@ -7,7 +7,6 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveZero /// /// See: http://issues.umbraco.org/issue/U4-8522 /// - [Migration("7.5.0", 2, Constants.System.UmbracoMigrationName)] public class UpdateUniqueIndexOnPropertyData : MigrationBase { public UpdateUniqueIndexOnPropertyData(IMigrationContext context) @@ -15,7 +14,7 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveZero { } - public override void Up() + public override void Migrate() { //Clear all stylesheet data if the tables exist //tuple = tablename, indexname, columnname, unique @@ -59,9 +58,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveZero .Do(); } } - - public override void Down() - { - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddIndexToDictionaryKeyColumn.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddIndexToDictionaryKeyColumn.cs index 8cbe349b2e..c372f44ead 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddIndexToDictionaryKeyColumn.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddIndexToDictionaryKeyColumn.cs @@ -3,14 +3,13 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero { - [Migration("7.7.0", 5, Constants.System.UmbracoMigrationName)] public class AddIndexToDictionaryKeyColumn : MigrationBase { public AddIndexToDictionaryKeyColumn(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var database = Database; //Now we need to check if we can actually do this because we won't be able to if there's data in there that is too long @@ -37,10 +36,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero .Do(); } } - - public override void Down() - { - Delete.Index("IX_cmsDictionary_key").OnTable("cmsDictionary").Do(); - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddUserGroupTables.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddUserGroupTables.cs index af308f1079..c08093f9f5 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddUserGroupTables.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddUserGroupTables.cs @@ -7,7 +7,6 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero { - [Migration("7.7.0", 5, Constants.System.UmbracoMigrationName)] public class AddUserGroupTables : MigrationBase { private readonly string _collateSyntax; @@ -23,7 +22,7 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero : "COLLATE DATABASE_DEFAULT"; } - public override void Up() + public override void Migrate() { var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToList(); var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddUserStartNodeTable.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddUserStartNodeTable.cs index 6647a73422..452083b33c 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddUserStartNodeTable.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/AddUserStartNodeTable.cs @@ -3,14 +3,13 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero { - [Migration("7.7.0", 5, Constants.System.UmbracoMigrationName)] public class AddUserStartNodeTable : MigrationBase { public AddUserStartNodeTable(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray(); diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/EnsureContentTemplatePermissions.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/EnsureContentTemplatePermissions.cs index def96bd334..7acf720ad6 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/EnsureContentTemplatePermissions.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/EnsureContentTemplatePermissions.cs @@ -7,14 +7,13 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero /// /// Ensures the built-in user groups have the blueprint permission by default on upgrade /// - [Migration("7.7.0", 5, Constants.System.UmbracoMigrationName)] public class EnsureContentTemplatePermissions : MigrationBase { public EnsureContentTemplatePermissions(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var database = Database; var userGroups = database.Fetch( diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/ReduceDictionaryKeyColumnsSize.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/ReduceDictionaryKeyColumnsSize.cs index 1070fabb8d..5017b122f9 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/ReduceDictionaryKeyColumnsSize.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/ReduceDictionaryKeyColumnsSize.cs @@ -3,14 +3,13 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero { - [Migration("7.7.0", 5, Constants.System.UmbracoMigrationName)] public class ReduceDictionaryKeyColumnsSize : MigrationBase { public ReduceDictionaryKeyColumnsSize(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { //Now we need to check if we can actually do this because we won't be able to if there's data in there that is too long diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/UpdateUserTables.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/UpdateUserTables.cs index 134bf729c7..85d96893cc 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/UpdateUserTables.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSevenZero/UpdateUserTables.cs @@ -6,14 +6,13 @@ using Umbraco.Core.Security; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero { - [Migration("7.7.0", 5, Constants.System.UmbracoMigrationName)] public class UpdateUserTables : MigrationBase { public UpdateUserTables(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { //Don't exeucte if the column is already there var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray(); diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs index 7b873c1088..5e4ee164e7 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs @@ -3,14 +3,13 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 3, Constants.System.UmbracoMigrationName)] public class AddIndexToCmsMemberLoginName : MigrationBase { public AddIndexToCmsMemberLoginName(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var database = Database; @@ -40,10 +39,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero .Do(); } } - - public override void Down() - { - Delete.Index("IX_cmsMember_LoginName").OnTable("cmsMember").Do(); - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToUmbracoNodePath.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToUmbracoNodePath.cs index acbd65e157..b04996d05c 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToUmbracoNodePath.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToUmbracoNodePath.cs @@ -3,14 +3,13 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] public class AddIndexToUmbracoNodePath : MigrationBase { public AddIndexToUmbracoNodePath(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database); @@ -25,10 +24,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero .Do(); } } - - public override void Down() - { - Delete.Index("IX_umbracoNodePath").OnTable("umbracoNode").Do(); - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToUser2NodePermission.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToUser2NodePermission.cs index c563c42637..eee7f192e1 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToUser2NodePermission.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexToUser2NodePermission.cs @@ -3,14 +3,13 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] public class AddIndexToUser2NodePermission : MigrationBase { public AddIndexToUser2NodePermission(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database); @@ -25,10 +24,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero .Do(); } } - - public override void Down() - { - Delete.Index("IX_umbracoUser2NodePermission_nodeId").OnTable("cmsMember").Do(); - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexesToUmbracoRelationTables.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexesToUmbracoRelationTables.cs index 6198d69d33..fc2cc7612c 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexesToUmbracoRelationTables.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddIndexesToUmbracoRelationTables.cs @@ -4,14 +4,13 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] public class AddIndexesToUmbracoRelationTables : MigrationBase { public AddIndexesToUmbracoRelationTables(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database).ToArray(); @@ -82,10 +81,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero } } - - public override void Down() - { - Delete.Index("IX_umbracoNodePath").OnTable("umbracoNode").Do(); - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddLockObjects.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddLockObjects.cs index bdf9513620..1b5c96b9fb 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddLockObjects.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddLockObjects.cs @@ -2,23 +2,17 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 101, Constants.System.UmbracoMigrationName)] public class AddLockObjects : MigrationBase { public AddLockObjects(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { EnsureLockObject(Constants.Locks.Servers, "Servers"); } - public override void Down() - { - // not implemented - } - private void EnsureLockObject(int id, string name) { var db = Database; diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddLockTable.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddLockTable.cs index 68a529085d..e76fe152c8 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddLockTable.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddLockTable.cs @@ -2,14 +2,13 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 100, Constants.System.UmbracoMigrationName)] public class AddLockTable : MigrationBase { public AddLockTable(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray(); if (tables.InvariantContains("umbracoLock") == false) @@ -21,10 +20,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero .Do(); } } - - public override void Down() - { - // not implemented - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs index 3afbdb981d..d4f54f830b 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs @@ -3,14 +3,13 @@ using System.Linq; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] public class AddMacroUniqueIdColumn : MigrationBase { public AddMacroUniqueIdColumn(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray(); @@ -65,10 +64,5 @@ JOIN cmsMacro ON cmsMacroProperty.macro=cmsMacro.id") foreach (var update in updates) database.Execute("UPDATE cmsMacroProperty set uniquePropertyId=@guid WHERE id=@id", new { guid = update.Item2, id = update.Item1 }); } - - public override void Down() - { - throw new NotImplementedException(); - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddRelationTypeUniqueIdColumn.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddRelationTypeUniqueIdColumn.cs index 4481f09575..e77b7b9e6e 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddRelationTypeUniqueIdColumn.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/AddRelationTypeUniqueIdColumn.cs @@ -3,14 +3,13 @@ using System.Linq; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] public class AddRelationTypeUniqueIdColumn : MigrationBase { public AddRelationTypeUniqueIdColumn(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray(); @@ -37,10 +36,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero foreach (var update in updates) database.Execute("UPDATE umbracoRelationType set typeUniqueId=@guid WHERE id=@id", new { guid = update.Item2, id = update.Item1 }); } - - public override void Down() - { - throw new NotImplementedException(); - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs index b98bd7ae9a..24b1bd28d7 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs @@ -4,14 +4,13 @@ using Umbraco.Core.Exceptions; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] public class NormalizeTemplateGuids : MigrationBase { public NormalizeTemplateGuids(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var database = Database; @@ -23,7 +22,7 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero // of 7.6 on Courier. // so... testing if we already have a 7.6.0 version installed. not pretty but...? // - var version = database.FirstOrDefault("SELECT version FROM umbracoMigration WHERE name=@name ORDER BY version DESC", new { name = Constants.System.UmbracoMigrationName }); + var version = database.FirstOrDefault("SELECT version FROM umbracoMigration WHERE name=@name ORDER BY version DESC", new { name = Constants.System.UmbracoUpgraderName }); if (version != null && version.StartsWith("7.6.0")) return; var updates = database.Query(@"SELECT umbracoNode.id, cmsTemplate.alias FROM umbracoNode @@ -35,10 +34,5 @@ WHERE nodeObjectType = @guid", new { guid = Constants.ObjectTypes.TemplateType } foreach (var update in updates) database.Execute("UPDATE umbracoNode set uniqueId=@guid WHERE id=@id", new { guid = update.Item2, id = update.Item1 }); } - - public override void Down() - { - throw new WontImplementException(); - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs index de63c58a8f..8a4825d7d0 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs @@ -3,14 +3,13 @@ using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 2, Constants.System.UmbracoMigrationName)] public class ReduceLoginNameColumnsSize : MigrationBase { public ReduceLoginNameColumnsSize(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { //Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long //http://issues.umbraco.org/issue/U4-9758 diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/RemovePropertyDataIdIndex.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/RemovePropertyDataIdIndex.cs index afa3185cb6..7ab6e04b01 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/RemovePropertyDataIdIndex.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/RemovePropertyDataIdIndex.cs @@ -5,14 +5,13 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero /// /// See: http://issues.umbraco.org/issue/U4-9188 /// - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] public class UpdateUniqueIndexOnPropertyData : MigrationBase { public UpdateUniqueIndexOnPropertyData(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { //tuple = tablename, indexname, columnname, unique var indexes = SqlSyntax.GetDefinedIndexes(Context.Database).ToArray(); @@ -26,9 +25,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero Delete.Index("IX_cmsPropertyData").OnTable("cmsPropertyData").Do(); } } - - public override void Down() - { - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/RemoveUmbracoDeployTables.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/RemoveUmbracoDeployTables.cs index 8f90f56b96..7a8a204807 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/RemoveUmbracoDeployTables.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/RemoveUmbracoDeployTables.cs @@ -3,14 +3,13 @@ using System.Linq; namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero { - [Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)] public class RemoveUmbracoDeployTables : MigrationBase { public RemoveUmbracoDeployTables(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray(); @@ -28,10 +27,5 @@ namespace Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero if (tables.InvariantContains("umbracoDeployChecksum")) Delete.Table("umbracoDeployChecksum").Do(); } - - public override void Down() - { - throw new NotImplementedException(); - } } } diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs new file mode 100644 index 0000000000..bcea9b643b --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -0,0 +1,104 @@ +using Umbraco.Core.Logging; +using Umbraco.Core.Migrations.Upgrade.TargetVersionEight; +using Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveFive; +using Umbraco.Core.Migrations.Upgrade.TargetVersionSevenFiveZero; +using Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSevenZero; +using Umbraco.Core.Migrations.Upgrade.TargetVersionSevenSixZero; +using Umbraco.Core.Scoping; + +namespace Umbraco.Core.Migrations.Upgrade +{ + /// + /// Represents Umbraco's migration plan. + /// + public class UmbracoPlan : MigrationPlan + { + public UmbracoPlan(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, ILogger logger) + : base("umbraco", scopeProvider, migrationBuilder, logger) + { + // INSTALL + // when installing, the source state is empty, and the target state should be the installed state, + // ie the common end state to all upgrade branches, representing the current version + Add(string.Empty, "{6550C7E8-77B7-4DE3-9B58-E31C81CB9504}"); + + // UPGRADE FROM 7 + // when 8.0.0 is released, on the first upgrade, the state is automatically + // set to {init-7.x.y} where 7.x.y is the version, detected from the database. + + From("{init-7.8.0}") + .Chain("{7C447271-CA3F-4A6A-A913-5D77015655CB}") // add more lock objects + .Chain("{CBFF58A2-7B50-4F75-8E98-249920DB0F37}") + .Chain("{3D18920C-E84D-405C-A06A-B7CEE52FE5DD}") + .Chain("{6550C7E8-77B7-4DE3-9B58-E31C81CB9504}"); + + // UPGRADE FROM 7 + // after 8.0.0 has been released we are going to release more v7 versions, which + // may backport some migrations, etc - so they would need their own upgrade path. + + // 7.8.1 = same as 7.8.0 + From("{init-7.8.1}") + .Chain("{init-7.8.0}"); + + // 7.9.0 = requires its own chain + From("{init-7.9.0}") + // chain... + .Chain("{6550C7E8-77B7-4DE3-9B58-E31C81CB9504}"); + + // UPGRADE 8 + // chain migrations for 8.0.1 etc + // should start from the install state when 8.0.0 is released, and chain + // migrations, and end with the new install state. + + //From("") + // .Chain("") + // .Chain(""); + + // WIP 8 + // during v8 development, we have existing v8 sites that we want to upgrade, + // and this requires merging in some v7 migrations. This chain should quite + // probably never be released. NOTE that when adding a migration at the bottom + // of this chain, one should update the installed state in the INSTALL and + // UPGRADE chains above. And, once 8.0.0 has been released, this chain should + // never ever change again. + + // 8.0.0 + From("{init-origin}"); + Chain("{98347B5E-65BF-4DD7-BB43-A09CB7AF4FCA}"); + Chain("{1E8165C4-942D-40DC-AC76-C5FF8831E400}"); + Chain("{39E15568-7AAD-4D54-81D0-758CCFC529F8}"); + Chain("{55C3F97D-BDA7-4FB1-A743-B0456B56EAA3}"); + + // 7.5.0 + Chain("{287F9E39-F673-42F7-908C-21659AB13B13}"); + Chain("{2D08588A-AD90-479C-9F6E-A99B60BA7226}"); + Chain("{2D917FF8-AC81-4C00-A407-1F4B1DF6089C}"); + + // 7.5.5 + Chain("{44484C32-EEB3-4A12-B1CB-11E02CE22AB2}"); + + // 7.6.0 + //Chain("{858B4039-070C-4928-BBEC-DDE8303352DA}"); + //Chain("{64F587C1-0B28-4D78-B4CC-26B7D87F69C1}"); + Chain("{3586E4E9-2922-49EB-8E2A-A530CE6DBDE0}"); + Chain("{D4A5674F-654D-4CC7-85E5-CFDBC533A318}"); + Chain("{7F828EDD-6622-4A8D-AD80-EEAF46C11680}"); + Chain("{F30AC223-D277-4D1F-B2AB-F0F0D3546CE1}"); + Chain("{7C27E310-CF48-4637-A22E-8D87355161C1}"); + Chain("{7D2ABA16-EE48-4569-8827-E81370FC4871}"); + Chain("{02879EDF-13A8-43AF-87A5-DD85723D0016}"); + Chain("{5496C6CC-3AE0-4789-AF49-5BB4E28FA424}"); + Chain("{8995332B-085E-4C0C-849E-9A77E79F4293}"); + + // 7.7.0 + Chain("{74319856-7681-46B1-AA0D-F7E896FBE6A1}"); + Chain("{0427B0A2-994A-4AB4-BFF3-31B20614F6C9}"); + Chain("{F0D6F782-E432-46DE-A3A7-2AF06DB8853B}"); + Chain("{AEB2BA2B-71E4-4B1B-AB6C-CEFB7F06FEEB}"); + Chain("{B5A6C799-B91E-496F-A1FE-7B4FE98BF6AB}"); + Chain("{04F54303-3055-4700-8F76-35A37F232FF5}"); + + // 8.0.0 + Chain("{6550C7E8-77B7-4DE3-9B58-E31C81CB9504}"); + } + } +} diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs new file mode 100644 index 0000000000..411dc1c92b --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs @@ -0,0 +1,57 @@ +using System; +using System.Configuration; +using Semver; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Scoping; +using Umbraco.Core.Services; + +namespace Umbraco.Core.Migrations.Upgrade +{ + public class UmbracoUpgrader : Upgrader + { + public UmbracoUpgrader(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations, ILogger logger) + : base(Constants.System.UmbracoUpgraderName, scopeProvider, migrationBuilder, keyValueService, postMigrations, logger) + { } + + protected override MigrationPlan GetPlan() + { + return new UmbracoPlan(ScopeProvider, MigrationBuilder, Logger); + } + + protected override string GetInitialState() + { + // no state in database yet - assume we have something in web.config that makes some sense + if (!SemVersion.TryParse(ConfigurationManager.AppSettings["umbracoConfigurationStatus"], out var currentVersion)) + throw new InvalidOperationException("Could not get current version from web.config umbracoConfigurationStatus appSetting."); + + // must be at least 7.8.0 - fixme adjust when releasing + if (currentVersion < new SemVersion(7, 8)) + throw new InvalidOperationException($"Version {currentVersion} cannot be upgraded to {UmbracoVersion.SemanticVersion}."); + + // cannot go back in time + if (currentVersion > UmbracoVersion.SemanticVersion) + throw new InvalidOperationException($"Version {currentVersion} cannot be upgraded to {UmbracoVersion.SemanticVersion}."); + + switch (currentVersion.Major) + { + case 7: + return "{orig-" + currentVersion + "}"; + case 8: // fixme remove when releasing + // this is very temp and for my own website - zpqrtbnk + return "{04F54303-3055-4700-8F76-35A37F232FF5}"; // right before the variants migration + default: + throw new InvalidOperationException($"Version {currentVersion} should have an upgrade state in the key-value table."); + } + } + + protected override (SemVersion, SemVersion) GetVersions() + { + // assume we have something in web.config that makes some sense + if (!SemVersion.TryParse(ConfigurationManager.AppSettings["umbracoConfigurationStatus"], out var currentVersion)) + throw new InvalidOperationException("Could not get current version from web.config umbracoConfigurationStatus appSetting."); + + return (currentVersion, UmbracoVersion.SemanticVersion); + } + } +} diff --git a/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs b/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs new file mode 100644 index 0000000000..a9ca8bd856 --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs @@ -0,0 +1,77 @@ +using System; +using Semver; +using Umbraco.Core.Exceptions; +using Umbraco.Core.Logging; +using Umbraco.Core.Scoping; +using Umbraco.Core.Services; + +namespace Umbraco.Core.Migrations.Upgrade +{ + public abstract class Upgrader + { + private readonly IKeyValueService _keyValueService; + private readonly PostMigrationCollection _postMigrations; + + protected Upgrader(string name, IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations, ILogger logger) + { + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name)); + Name = name; + StateValueKey = "Umbraco.Core.Upgrader.State+" + name; + + ScopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider)); + MigrationBuilder = migrationBuilder ?? throw new ArgumentNullException(nameof(migrationBuilder)); + _keyValueService = keyValueService ?? throw new ArgumentNullException(nameof(keyValueService)); + _postMigrations = postMigrations ?? throw new ArgumentNullException(nameof(postMigrations)); + Logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public string Name { get; } + + public string StateValueKey { get; } + + protected IScopeProvider ScopeProvider { get; } + + protected IMigrationBuilder MigrationBuilder { get; } + + protected ILogger Logger { get; } + + protected abstract MigrationPlan GetPlan(); + protected abstract string GetInitialState(); + protected abstract (SemVersion, SemVersion) GetVersions(); + + public void Execute() + { + var plan = GetPlan(); + + using (var scope = ScopeProvider.CreateScope()) + { + // read current state + var currentState = _keyValueService.GetValue(StateValueKey) ?? string.Empty; + var forceState = false; + + if (currentState == string.Empty) + { + currentState = GetInitialState(); + forceState = true; + } + + (var originVersion, var targetVersion) = GetVersions(); + + // execute plan + var state = plan.Execute(scope, currentState); + + // save new state + if (forceState) + _keyValueService.SetValue(StateValueKey, state); + else + _keyValueService.SetValue(StateValueKey, currentState, state); + + // run post-migrations + foreach (var postMigration in _postMigrations) + postMigration.Execute(Name, scope, originVersion, targetVersion, Logger); + + scope.Complete(); + } + } + } +} diff --git a/src/Umbraco.Core/Models/Rdbms/KeyValueDto.cs b/src/Umbraco.Core/Models/Rdbms/KeyValueDto.cs new file mode 100644 index 0000000000..a27b137d2a --- /dev/null +++ b/src/Umbraco.Core/Models/Rdbms/KeyValueDto.cs @@ -0,0 +1,26 @@ +using System; +using NPoco; +using Umbraco.Core.Persistence.DatabaseAnnotations; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; + +namespace Umbraco.Core.Models.Rdbms +{ + [TableName(Constants.DatabaseSchema.Tables.KeyValue)] + [PrimaryKey("key")] + [ExplicitColumns] + internal class KeyValueDto + { + [Column("key")] + [Length(256)] + [PrimaryKeyColumn(AutoIncrement = false, Clustered = true)] + public string Key { get; set; } + + [Column("value")] + [NullSetting(NullSetting = NullSettings.Null)] + public string Value { get; set; } + + [Column("updated")] + [Constraint(Default = SystemMethods.CurrentDateTime)] + public DateTime Updated { get; set; } + } +} diff --git a/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs b/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs index 661f9be3db..8be8e68af9 100644 --- a/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs +++ b/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs @@ -71,6 +71,8 @@ namespace Umbraco.Core public const string Task = /*TableNamePrefix*/ "cms" + "Task"; public const string TaskType = /*TableNamePrefix*/ "cms" + "TaskType"; + + public const string KeyValue = TableNamePrefix + "KeyValue"; } } } diff --git a/src/Umbraco.Core/Persistence/Constants-Locks.cs b/src/Umbraco.Core/Persistence/Constants-Locks.cs index 89d7cf7391..6f5d4bb0dc 100644 --- a/src/Umbraco.Core/Persistence/Constants-Locks.cs +++ b/src/Umbraco.Core/Persistence/Constants-Locks.cs @@ -13,6 +13,7 @@ namespace Umbraco.Core public const int MediaTypes = -336; public const int MemberTypes = -337; public const int Domains = -338; + public const int KeyValues = -339; } } } diff --git a/src/Umbraco.Core/Services/IKeyValueService.cs b/src/Umbraco.Core/Services/IKeyValueService.cs new file mode 100644 index 0000000000..35faf19160 --- /dev/null +++ b/src/Umbraco.Core/Services/IKeyValueService.cs @@ -0,0 +1,9 @@ +namespace Umbraco.Core.Services +{ + public interface IKeyValueService + { + string GetValue(string key); + void SetValue(string key, string value); + void SetValue(string key, string originValue, string newValue); + } +} diff --git a/src/Umbraco.Core/Services/Implement/KeyValueService.cs b/src/Umbraco.Core/Services/Implement/KeyValueService.cs new file mode 100644 index 0000000000..6ecf642c7b --- /dev/null +++ b/src/Umbraco.Core/Services/Implement/KeyValueService.cs @@ -0,0 +1,124 @@ +using System; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Migrations; +using Umbraco.Core.Migrations.Expressions.Create; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Scoping; +using Umbraco.Core.Persistence; + +namespace Umbraco.Core.Services.Implement +{ + internal class KeyValueService : IKeyValueService + { + private readonly object _initialock = new object(); + private readonly IScopeProvider _scopeProvider; + private readonly ILogger _logger; + private bool _initialized; + + public KeyValueService(IScopeProvider scopeProvider, ILogger logger) + { + _scopeProvider = scopeProvider; + _logger = logger; + } + + private void EnsureInitialized() + { + lock (_initialock) + { + if (_initialized) return; + Initialize(); + _initialized = true; + } + } + + private void Initialize() + { + using (var scope = _scopeProvider.CreateScope()) + { + if (!scope.Database.Exists(Constants.Locks.KeyValues)) + scope.Database.Execute($@"INSERT {scope.SqlContext.SqlSyntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.Lock)} (id, name, value) +VALUES ({Constants.Locks.KeyValues}, 'KeyValues', 1);"); + + if (!scope.SqlContext.SqlSyntax.DoesTableExist(scope.Database, Constants.DatabaseSchema.Tables.KeyValue)) + { + var context = new MigrationContext(scope.Database, _logger); + new CreateBuilder(context).Table().Do(); + } + + scope.Complete(); + } + } + + public string GetValue(string key) + { + EnsureInitialized(); + + using (var scope = _scopeProvider.CreateScope()) + { + var sql = scope.SqlContext.Sql().Select().From().Where(x => x.Key == key); + var dto = scope.Database.Fetch(sql).FirstOrDefault(); + scope.Complete(); + return dto?.Value; + } + } + + public void SetValue(string key, string value) + { + EnsureInitialized(); + + using (var scope = _scopeProvider.CreateScope()) + { + scope.WriteLock(Constants.Locks.KeyValues); + + var sql = scope.SqlContext.Sql().Select().From().Where(x => x.Key == key); + var dto = scope.Database.Fetch(sql).FirstOrDefault(); + + if (dto == null) + { + dto = new KeyValueDto + { + Key = key, + Value = value, + Updated = DateTime.Now + }; + + scope.Database.Insert(dto); + } + else + { + dto.Value = value; + dto.Updated = DateTime.Now; + scope.Database.Update(dto); + } + + scope.Complete(); + } + } + + public void SetValue(string key, string originValue, string newValue) + { + EnsureInitialized(); + + using (var scope = _scopeProvider.CreateScope()) + { + scope.WriteLock(Constants.Locks.KeyValues); + + var sql = scope.SqlContext.Sql().Select().From().Where(x => x.Key == key); + var dto = scope.Database.Fetch(sql).FirstOrDefault(); + + if (dto == null) + throw new InvalidOperationException("Key not found."); + + if (dto.Value != originValue) + throw new InvalidOperationException("Value has changed."); + + dto.Value = newValue; + dto.Updated = DateTime.Now; + scope.Database.Update(dto); + + scope.Complete(); + } + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 7d34e099c3..89dd584850 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -319,6 +319,7 @@ + @@ -521,7 +522,16 @@ - + + + + + + + + + + @@ -696,6 +706,7 @@ + @@ -889,18 +900,14 @@ - - - - @@ -1000,13 +1007,9 @@ - - + - - - @@ -1321,6 +1324,7 @@ + @@ -1333,6 +1337,7 @@ + @@ -1468,8 +1473,6 @@ - - - + \ No newline at end of file diff --git a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs index 0210da3318..0f76d11f3f 100644 --- a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs @@ -2,7 +2,6 @@ using System.Linq; using Moq; using NUnit.Framework; -using Semver; using Umbraco.Core.Logging; using Umbraco.Core.Migrations; using Umbraco.Core.Migrations.Install; @@ -23,9 +22,9 @@ namespace Umbraco.Tests.Migrations { var logger = new DebugDiagnosticsLogger(); - var builder = Mock.Of(); + var builder = Mock.Of(); Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) + .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => { if (t != typeof(CreateTableOfTDtoMigration)) @@ -35,21 +34,11 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var runner = new MigrationRunner( - ScopeProvider, - builder, - Mock.Of(), - logger, - new SemVersion(0), // 0.0.0 - new SemVersion(1), // 1.0.0 - "Test", + var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", ScopeProvider, builder, logger) + .Add(string.Empty, "done")); - // explicit migrations - typeof(CreateTableOfTDtoMigration) - ); - - var upgraded = runner.Execute(); - Assert.IsTrue(upgraded); + upgrader.Execute(); var helper = new DatabaseSchemaCreator(scope.Database, logger); var exists = helper.TableExists("umbracoNode"); @@ -64,9 +53,9 @@ namespace Umbraco.Tests.Migrations { var logger = new DebugDiagnosticsLogger(); - var builder = Mock.Of(); + var builder = Mock.Of(); Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) + .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => { switch (t.Name) @@ -82,23 +71,12 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var runner = new MigrationRunner( - ScopeProvider, - builder, - Mock.Of(), - logger, - new SemVersion(0), // 0.0.0 - new SemVersion(1), // 1.0.0 - "Test", - - // explicit migrations - typeof(CreateTableOfTDtoMigration), - typeof(DeleteKeysAndIndexesMigration) - ); - - var upgraded = runner.Execute(); - Assert.IsTrue(upgraded); + var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", ScopeProvider, builder, logger) + .Add(string.Empty, "a") + .Add("a", "done")); + upgrader.Execute(); scope.Complete(); } } @@ -108,9 +86,9 @@ namespace Umbraco.Tests.Migrations { var logger = new DebugDiagnosticsLogger(); - var builder = Mock.Of(); + var builder = Mock.Of(); Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) + .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => { switch (t.Name) @@ -128,24 +106,13 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var runner = new MigrationRunner( - ScopeProvider, - builder, - Mock.Of(), - logger, - new SemVersion(0), // 0.0.0 - new SemVersion(1), // 1.0.0 - "Test", - - // explicit migrations - typeof(CreateTableOfTDtoMigration), - typeof(DeleteKeysAndIndexesMigration), - typeof(CreateKeysAndIndexesOfTDtoMigration) - ); - - var upgraded = runner.Execute(); - Assert.IsTrue(upgraded); + var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", ScopeProvider, builder, logger) + .Add(string.Empty, "a") + .Add("a", "b") + .Add("b", "done")); + upgrader.Execute(); scope.Complete(); } } @@ -155,9 +122,9 @@ namespace Umbraco.Tests.Migrations { var logger = new DebugDiagnosticsLogger(); - var builder = Mock.Of(); + var builder = Mock.Of(); Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) + .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => { switch (t.Name) @@ -175,24 +142,13 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var runner = new MigrationRunner( - ScopeProvider, - builder, - Mock.Of(), - logger, - new SemVersion(0), // 0.0.0 - new SemVersion(1), // 1.0.0 - "Test", - - // explicit migrations - typeof(CreateTableOfTDtoMigration), - typeof(DeleteKeysAndIndexesMigration), - typeof(CreateKeysAndIndexesMigration) - ); - - var upgraded = runner.Execute(); - Assert.IsTrue(upgraded); + var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", ScopeProvider, builder, logger) + .Add(string.Empty, "a") + .Add("a", "b") + .Add("b", "done")); + upgrader.Execute(); scope.Complete(); } } @@ -202,9 +158,9 @@ namespace Umbraco.Tests.Migrations { var logger = new DebugDiagnosticsLogger(); - var builder = Mock.Of(); + var builder = Mock.Of(); Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) + .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => { switch (t.Name) @@ -220,50 +176,36 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var runner = new MigrationRunner( - ScopeProvider, - builder, - Mock.Of(), - logger, - new SemVersion(0), // 0.0.0 - new SemVersion(1), // 1.0.0 - "Test", - - // explicit migrations - typeof(CreateTableOfTDtoMigration), - typeof(CreateColumnMigration) - ); - - var upgraded = runner.Execute(); - Assert.IsTrue(upgraded); + var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", ScopeProvider, builder, logger) + .Add(string.Empty, "a") + .Add("a", "done")); + upgrader.Execute(); scope.Complete(); } - } - [Migration("1.0.0", 0, "Test")] public class CreateTableOfTDtoMigration : MigrationBase { public CreateTableOfTDtoMigration(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { // creates Node table with keys, indexes, etc Create.Table().Do(); } } - [Migration("1.0.0", 1, "Test")] public class DeleteKeysAndIndexesMigration : MigrationBase { public DeleteKeysAndIndexesMigration(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { // drops Node table keys and indexes //Execute.DropKeysAndIndexes("umbracoNode"); @@ -273,28 +215,26 @@ namespace Umbraco.Tests.Migrations } } - [Migration("1.0.0", 2, "Test")] public class CreateKeysAndIndexesOfTDtoMigration : MigrationBase { public CreateKeysAndIndexesOfTDtoMigration(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { // creates Node table keys and indexes Create.KeysAndIndexes().Do(); } } - [Migration("1.0.0", 3, "Test")] public class CreateKeysAndIndexesMigration : MigrationBase { public CreateKeysAndIndexesMigration(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { // creates *all* tables keys and indexes foreach (var x in DatabaseSchemaCreator.OrderedTables) @@ -307,14 +247,13 @@ namespace Umbraco.Tests.Migrations } } - [Migration("1.0.0", 2, "Test")] public class CreateColumnMigration : MigrationBase { public CreateColumnMigration(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { // cannot delete the column without this, of course Delete.KeysAndIndexes().Do(); diff --git a/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs b/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs index 941ec36cc8..962fd9f975 100644 --- a/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/AlterMigrationTests.cs @@ -42,7 +42,7 @@ namespace Umbraco.Tests.Migrations var stub = new DropForeignKeyMigrationStub(context); // Act - stub.Up(); + stub.Migrate(); foreach (var op in database.Operations) Console.WriteLine("{0}\r\n\t{1}", op.Text, op.Sql); @@ -60,7 +60,7 @@ namespace Umbraco.Tests.Migrations var context = new MigrationContext(database, _logger); var migration = new CreateColumnMigration(context); - migration.Up(); + migration.Migrate(); foreach (var op in database.Operations) Console.WriteLine("{0}\r\n\t{1}", op.Text, op.Sql); @@ -69,20 +69,16 @@ namespace Umbraco.Tests.Migrations Assert.That(database.Operations[0].Sql, Is.EqualTo("ALTER TABLE [bar] ADD [foo] UniqueIdentifier NOT NULL")); } - [Migration("1.0.0", 0, "Test")] public class CreateColumnMigration : MigrationBase { public CreateColumnMigration(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { Alter.Table("bar").AddColumn("foo").AsGuid().Do(); } - - public override void Down() - { } } [Test] @@ -92,7 +88,7 @@ namespace Umbraco.Tests.Migrations var context = new MigrationContext(database, _logger); var migration = new AlterColumnMigration(context); - migration.Up(); + migration.Migrate(); foreach (var op in database.Operations) Console.WriteLine("{0}\r\n\t{1}", op.Text, op.Sql); @@ -101,22 +97,18 @@ namespace Umbraco.Tests.Migrations Assert.That(database.Operations[0].Sql, Is.EqualTo("ALTER TABLE [bar] ALTER COLUMN [foo] UniqueIdentifier NOT NULL")); } - [Migration("1.0.0", 0, "Test")] public class AlterColumnMigration : MigrationBase { public AlterColumnMigration(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { // bad/good syntax... //Alter.Column("foo").OnTable("bar").AsGuid().NotNullable(); Alter.Table("bar").AlterColumn("foo").AsGuid().NotNullable().Do(); } - - public override void Down() - { } } [NUnit.Framework.Ignore("this doesn't actually test anything")] @@ -129,7 +121,7 @@ namespace Umbraco.Tests.Migrations var stub = new AlterUserTableMigrationStub(context); // Act - stub.Up(); + stub.Migrate(); // Assert Assert.That(database.Operations.Any(), Is.True); diff --git a/src/Umbraco.Tests/Migrations/FindingMigrationsTest.cs b/src/Umbraco.Tests/Migrations/FindingMigrationsTest.cs deleted file mode 100644 index fc9c3c8284..0000000000 --- a/src/Umbraco.Tests/Migrations/FindingMigrationsTest.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Migrations; -using Umbraco.Tests.Migrations.Stubs; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.Migrations -{ - [TestFixture] - public class FindingMigrationsTest : TestWithDatabaseBase - { - [Test] - public void Can_Find_Migrations_With_Target_Version_Six() - { - var builder = new MigrationCollectionBuilder(Container) - .Add() - .Add() - .Add() - .Add() - .Add() - .Add(); - - var foundMigrations = builder.MigrationTypes; - var targetVersion = new Version("6.0.0"); - var list = new List(); - - foreach (var migration in foundMigrations) - { - var migrationAttribute = migration.FirstAttribute(); - if (migrationAttribute != null) - { - if (migrationAttribute.TargetVersion == targetVersion) - { - list.Add(migration); - } - } - } - - Assert.That(list.Count, Is.EqualTo(3)); - - // migrations Up actually executes in v8 - //foreach (var migration1 in list) - //{ - // var migration = (MigrationBase) migration1; - // migration.Up(); - //} - - //Assert.That(context.Expressions.Any(), Is.True); - - ////Console output - //foreach (var expression in context.Expressions) - //{ - // Debug.Print(expression.ToString()); - //} - } - } -} diff --git a/src/Umbraco.Tests/Migrations/MigrationIssuesTests.cs b/src/Umbraco.Tests/Migrations/MigrationIssuesTests.cs deleted file mode 100644 index daadc657a9..0000000000 --- a/src/Umbraco.Tests/Migrations/MigrationIssuesTests.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Diagnostics; -using System.Linq; -using Moq; -using NUnit.Framework; -using Semver; -using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; -using Umbraco.Core.Migrations.Upgrade.TargetVersionEight; -using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.Testing; - -namespace Umbraco.Tests.Migrations -{ - [TestFixture] - [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class MigrationIssuesTests : TestWithDatabaseBase - { - [Test] - public void Issue8361Test() - { - var logger = new DebugDiagnosticsLogger(); - - var builder = Mock.Of(); - Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) - .Returns((t, c) => - { - switch (t.Name) - { - case "DeleteRedirectUrlTable": - return new DeleteRedirectUrlTable(c); - case "AddRedirectUrlTable": - return new AddRedirectUrlTable(c); - default: - throw new NotSupportedException(); - } - }); - - using (var scope = Current.ScopeProvider.CreateScope()) - { - //Setup the MigrationRunner - var migrationRunner = new MigrationRunner( - ScopeProvider, - builder, - Mock.Of(), - logger, - new SemVersion(7, 5, 0), - new SemVersion(8, 0, 0), - Constants.System.UmbracoMigrationName, - - //pass in explicit migrations - typeof(DeleteRedirectUrlTable), - typeof(AddRedirectUrlTable) - ); - - var upgraded = migrationRunner.Execute(); - Assert.IsTrue(upgraded); - } - } - - [Migration("8.0.0", 99, Constants.System.UmbracoMigrationName)] - public class DeleteRedirectUrlTable : MigrationBase - { - public DeleteRedirectUrlTable(IMigrationContext context) - : base(context) - { } - - public override void Up() - { - Delete.Table("umbracoRedirectUrl"); - } - - public override void Down() - { } - } - } -} diff --git a/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs b/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs new file mode 100644 index 0000000000..328d300cab --- /dev/null +++ b/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs @@ -0,0 +1,151 @@ +using System; +using Moq; +using NPoco; +using NUnit.Framework; +using Umbraco.Core.Logging; +using Umbraco.Core.Migrations; +using Umbraco.Core.Migrations.Upgrade; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Scoping; +using Umbraco.Core.Services; +using Umbraco.Tests.Testing; + +namespace Umbraco.Tests.Migrations +{ + [TestFixture] + public class MigrationPlanTests + { + [Test] + public void CanExecute() + { + var logger = Mock.Of(); + + var database = new TestDatabase(); + var scope = Mock.Of(); + Mock.Get(scope) + .Setup(x => x.Database) + .Returns(database); + + var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); + var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext }; + + var migrationBuilder = Mock.Of(); + Mock.Get(migrationBuilder) + .Setup(x => x.Build(It.IsAny(), It.IsAny())) + .Returns((t, c) => + { + switch (t.Name) + { + case "DeleteRedirectUrlTable": + return new DeleteRedirectUrlTable(c); + case "NopMigration": + return new NopMigration(); + default: + throw new NotSupportedException(); + } + }); + + // fixme - NOT a migration collection builder, just a migration builder + // done, remove everywhere else, and delete migrationCollection stuff entirely + + var plan = new MigrationPlan("default", scopeProvider, migrationBuilder, logger) + .From(string.Empty) + .Chain("{4A9A1A8F-0DA1-4BCF-AD06-C19D79152E35}") + .Chain("VERSION.33"); + + var kvs = Mock.Of(); + Mock.Get(kvs).Setup(x => x.GetValue(It.IsAny())).Returns(k => k == "Umbraco.Tests.MigrationPlan" ? string.Empty : null); + + string state; + using (var s = scopeProvider.CreateScope()) + { + // read current state + var sourceState = kvs.GetValue("Umbraco.Tests.MigrationPlan") ?? string.Empty; + + // execute plan + state = plan.Execute(s, sourceState); + + // save new state + kvs.SetValue("Umbraco.Tests.MigrationPlan", sourceState, state); + + // fixme - what about post-migrations? + s.Complete(); + } + + Assert.AreEqual("VERSION.33", state); + Assert.AreEqual(1, database.Operations.Count); + Assert.AreEqual("DROP TABLE [umbracoRedirectUrl]", database.Operations[0].Sql); + } + + [Test] + public void CanAddMigrations() + { + var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + plan.Add(string.Empty, "aaa"); + plan.Add("aaa", "bbb"); + plan.Add("bbb", "ccc"); + } + + [Test] + public void CannotTransitionToSameState() + { + var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + Assert.Throws(() => + { + plan.Add("aaa", "aaa"); + }); + } + + [Test] + public void OnlyOneTransitionPerState() + { + var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + plan.Add("aaa", "bbb"); + Assert.Throws(() => + { + plan.Add("aaa", "ccc"); + }); + } + + [Test] + public void CannotContainTwoMoreHeads() + { + var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + plan.Add(string.Empty, "aaa"); + plan.Add("aaa", "bbb"); + plan.Add("ccc", "ddd"); + Assert.Throws(plan.Validate); + } + + [Test] + public void CannotContainLoops() + { + var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + plan.Add(string.Empty, "aaa"); + plan.Add("aaa", "bbb"); + plan.Add("bbb", "ccc"); + plan.Add("ccc", "aaa"); + Assert.Throws(plan.Validate); + } + + [Test] + public void ValidateUmbracoPlan() + { + var plan = new UmbracoPlan(Mock.Of(), Mock.Of(), Mock.Of()); + plan.Validate(); + } + + public class DeleteRedirectUrlTable : MigrationBase + { + public DeleteRedirectUrlTable(IMigrationContext context) + : base(context) + { } + + public override void Migrate() + { + Delete.Table("umbracoRedirectUrl").Do(); + } + } + } +} diff --git a/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs b/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs deleted file mode 100644 index 947b9dd9bd..0000000000 --- a/src/Umbraco.Tests/Migrations/MigrationRunnerTests.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using Moq; -using NPoco; -using NUnit.Framework; -using Semver; -using Umbraco.Core.Events; -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; -using Umbraco.Core.Migrations.Expressions.Alter.Expressions; -using Umbraco.Core.Persistence; -using Umbraco.Core.Scoping; -using Umbraco.Core.Services; -using Umbraco.Tests.Testing; - -namespace Umbraco.Tests.Migrations -{ - [TestFixture] - public class MigrationRunnerTests - { - private ILogger _logger; - - [SetUp] - public void Setup() - { - _logger = Mock.Of(); - } - - [Test] - public void Executes_Only_One_Migration_For_Spanning_Multiple_Targets() - { - var database = new TestDatabase(); - var scope = Mock.Of(); - Mock.Get(scope) - .Setup(x => x.Database) - .Returns(database); - - var builder = Mock.Of(); - Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) - .Returns((t, c) => - { - if (t != typeof(MultiMigration)) - throw new NotSupportedException(); - return new MultiMigration(c) as IMigration; - }); - - var runner = new MigrationRunner( - new TestScopeProvider(scope), - builder, - Mock.Of(), - _logger, new SemVersion(4 /*, 0, 0*/), new SemVersion(6 /*, 0, 0*/), "Test"); - - var types = runner.OrderedUpgradeMigrations(new[] { typeof(MultiMigration) }).ToArray(); - Assert.AreEqual(1, types.Length); - - var context = new MigrationContext(database, Mock.Of()); - var migrations = types.Select(x => builder.Instanciate(x, context)); - - runner.ExecuteMigrations(migrations /*, true*/); - Assert.AreEqual(1, database.Operations.Count); - } - - [Test] - public void Executes_Migration_For_Spanning_One_Target_1() - { - var database = new TestDatabase(); - var scope = Mock.Of(); - Mock.Get(scope) - .Setup(x => x.Database) - .Returns(database); - - var builder = Mock.Of(); - Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) - .Returns((t, c) => - { - if (t != typeof(MultiMigration)) - throw new NotSupportedException(); - return new MultiMigration(c) as IMigration; - }); - - var runner = new MigrationRunner( - new TestScopeProvider(scope), - builder, - Mock.Of(), - _logger, new SemVersion(4 /*, 0, 0*/), new SemVersion(5 /*, 0, 0*/), "Test"); - - var types = runner.OrderedUpgradeMigrations(new[] { typeof(MultiMigration) }).ToArray(); - - var context = new MigrationContext(database, Mock.Of()); - var migrations = types.Select(x => builder.Instanciate(x, context)); - - runner.ExecuteMigrations(migrations /*, true*/); - - Assert.AreEqual(1, database.Operations.Count); - } - - [Test] - public void Executes_Migration_For_Spanning_One_Target_2() - { - var database = new TestDatabase(); - var scope = Mock.Of(); - Mock.Get(scope) - .Setup(x => x.Database) - .Returns(database); - - var scopeProvider = Mock.Of(); - Mock.Get(scopeProvider) - .Setup(x => x.CreateScope(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(scope); - - var builder = Mock.Of(); - Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) - .Returns((t, c) => - { - if (t != typeof(MultiMigration)) - throw new NotSupportedException(); - return new MultiMigration(c); - }); - - var runner = new MigrationRunner( - scopeProvider, - builder, - Mock.Of(), - _logger, new SemVersion(5, 0, 1), new SemVersion(6 /*, 0, 0*/), "Test"); - - var types = runner.OrderedUpgradeMigrations(new[] { typeof(MultiMigration) }).ToArray(); - - var context = new MigrationContext(database, Mock.Of()); - var migrations = types.Select(x => builder.Instanciate(x, context)); - - runner.ExecuteMigrations(migrations /*, true*/); - - Assert.AreEqual(1, database.Operations.Count); - } - - [Migration("6.0.0", 1, "Test")] - [Migration("5.0.0", 1, "Test")] - private class MultiMigration : MigrationBase - { - public MultiMigration(IMigrationContext context) - : base(context) - { } - - public override void Up() - { - Alter.Table("table").AlterColumn("column").AsString().Do(); - } - - public override void Down() - { - Alter.Table("table").AlterColumn("column").AsString().Do(); - } - } - - public class TestScopeProvider : IScopeProvider - { - private readonly IScope _scope; - - public TestScopeProvider(IScope scope) - { - _scope = scope; - } - - public IScope CreateScope(IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null, bool callContext = false, bool autoComplete = false) - { - return _scope; - } - - public IScope CreateDetachedScope(IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null) - { - throw new NotImplementedException(); - } - - public void AttachScope(IScope scope, bool callContext = false) - { - throw new NotImplementedException(); - } - - public IScope DetachScope() - { - throw new NotImplementedException(); - } - - public IScopeContext Context { get; set; } - public ISqlContext SqlContext { get; set; } - } - } -} diff --git a/src/Umbraco.Tests/Migrations/MigrationTests.cs b/src/Umbraco.Tests/Migrations/MigrationTests.cs new file mode 100644 index 0000000000..67863e9494 --- /dev/null +++ b/src/Umbraco.Tests/Migrations/MigrationTests.cs @@ -0,0 +1,76 @@ +using System; +using System.Data; +using Semver; +using Umbraco.Core.Events; +using Umbraco.Core.Logging; +using Umbraco.Core.Migrations; +using Umbraco.Core.Migrations.Upgrade; +using Umbraco.Core.Persistence; +using Umbraco.Core.Scoping; +using Umbraco.Core.Services; + +namespace Umbraco.Tests.Migrations +{ + public class MigrationTests + { + public class TestUpgrader : Upgrader + { + private readonly MigrationPlan _plan; + + public TestUpgrader(string name, IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations, ILogger logger, MigrationPlan plan) + : base(name, scopeProvider, migrationBuilder, keyValueService, postMigrations, logger) + { + _plan = plan; + } + + protected override MigrationPlan GetPlan() + { + return _plan; + } + + protected override string GetInitialState() + { + return string.Empty; + } + + protected override (SemVersion, SemVersion) GetVersions() + { + return (new SemVersion(0), new SemVersion(0)); + } + } + + + public class TestScopeProvider : IScopeProvider + { + private readonly IScope _scope; + + public TestScopeProvider(IScope scope) + { + _scope = scope; + } + + public IScope CreateScope(IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null, bool callContext = false, bool autoComplete = false) + { + return _scope; + } + + public IScope CreateDetachedScope(IsolationLevel isolationLevel = IsolationLevel.Unspecified, RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null) + { + throw new NotImplementedException(); + } + + public void AttachScope(IScope scope, bool callContext = false) + { + throw new NotImplementedException(); + } + + public IScope DetachScope() + { + throw new NotImplementedException(); + } + + public IScopeContext Context { get; set; } + public ISqlContext SqlContext { get; set; } + } + } +} diff --git a/src/Umbraco.Tests/Migrations/PostMigrationTests.cs b/src/Umbraco.Tests/Migrations/PostMigrationTests.cs index 08109e85b7..18fe4c36db 100644 --- a/src/Umbraco.Tests/Migrations/PostMigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/PostMigrationTests.cs @@ -8,52 +8,37 @@ using Umbraco.Core; using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Migrations; -using Umbraco.Core.Migrations.Upgrade.TargetVersionEight; +using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -using Umbraco.Web.Strategies.Migrations; namespace Umbraco.Tests.Migrations { [TestFixture] public class PostMigrationTests { - private class NopMigration : MigrationBase - { - public NopMigration(IMigrationContext context) : base(context) - { } - - public override void Up() - { } - - public override void Down() - { } - } - [Test] public void Executes_For_Any_Product_Name_When_Not_Specified() { var logger = Mock.Of(); var changed1 = new Args { CountExecuted = 0 }; - var testHandler1 = new TestMigrationHandler(changed1); - MigrationRunner.Migrated += testHandler1.Migrated; + var post1 = new TestPostMigration(changed1); - var builder = Mock.Of(); + var posts = new PostMigrationCollection(new [] { post1 }); + + var builder = Mock.Of(); Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) + .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => { switch (t.Name) { - case "DeleteRedirectUrlTable": - return new MigrationIssuesTests.DeleteRedirectUrlTable(c); - case "AddRedirectUrlTable": - return new AddRedirectUrlTable(c); + case "NopMigration": + return new NopMigration(); default: throw new NotSupportedException(); } @@ -66,17 +51,13 @@ namespace Umbraco.Tests.Migrations .Returns(database); var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); - var scopeProvider = new MigrationRunnerTests.TestScopeProvider(scope) { SqlContext = sqlContext }; + var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext }; - var runner1 = new MigrationRunner( - scopeProvider, - builder, - Mock.Of(), - logger, - new SemVersion(1), new SemVersion(2), "Test1", - typeof(NopMigration)); + var u1 = new MigrationTests.TestUpgrader("Test", scopeProvider, builder, Mock.Of(), posts, logger, + new MigrationPlan("Test", scopeProvider, builder, logger) + .Add(string.Empty, "done")); + u1.Execute(); - var result1 = runner1.Execute(); Assert.AreEqual(1, changed1.CountExecuted); } @@ -86,24 +67,22 @@ namespace Umbraco.Tests.Migrations var logger = Mock.Of(); var changed1 = new Args { CountExecuted = 0}; - var testHandler1 = new TestMigrationHandler("Test1", changed1); - MigrationRunner.Migrated += testHandler1.Migrated; + var post1 = new TestPostMigration("Test1", changed1); var changed2 = new Args { CountExecuted = 0 }; - var testHandler2 = new TestMigrationHandler("Test2", changed2); - MigrationRunner.Migrated += testHandler2.Migrated; + var post2 = new TestPostMigration("Test2", changed2); - var builder = Mock.Of(); + var posts = new PostMigrationCollection(new [] { post1, post2 }); + + var builder = Mock.Of(); Mock.Get(builder) - .Setup(x => x.Instanciate(It.IsAny(), It.IsAny())) + .Setup(x => x.Build(It.IsAny(), It.IsAny())) .Returns((t, c) => { switch (t.Name) { - case "DeleteRedirectUrlTable": - return new MigrationIssuesTests.DeleteRedirectUrlTable(c); - case "AddRedirectUrlTable": - return new AddRedirectUrlTable(c); + case "NopMigration": + return new NopMigration(); default: throw new NotSupportedException(); } @@ -116,29 +95,21 @@ namespace Umbraco.Tests.Migrations .Returns(database); var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); - var scopeProvider = new MigrationRunnerTests.TestScopeProvider(scope) { SqlContext = sqlContext }; + var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext }; - var runner1 = new MigrationRunner( - scopeProvider, - builder, - Mock.Of(), - logger, - new SemVersion(1), new SemVersion(2), "Test1", - typeof(NopMigration)); + var u1 = new MigrationTests.TestUpgrader("Test1", scopeProvider, builder, Mock.Of(), posts, logger, + new MigrationPlan("Test1", scopeProvider, builder, logger) + .Add(string.Empty, "done")); + u1.Execute(); - var result1 = runner1.Execute(); Assert.AreEqual(1, changed1.CountExecuted); Assert.AreEqual(0, changed2.CountExecuted); - var runner2 = new MigrationRunner( - scopeProvider, - builder, - Mock.Of(), - logger, - new SemVersion(1), new SemVersion(2), "Test2", - typeof(NopMigration)); + var u2 = new MigrationTests.TestUpgrader("Test2", scopeProvider, builder, Mock.Of(), posts, logger, + new MigrationPlan("Test2", scopeProvider, builder, logger) + .Add(string.Empty, "done")); + u2.Execute(); - var result2 = runner2.Execute(); Assert.AreEqual(1, changed1.CountExecuted); Assert.AreEqual(1, changed2.CountExecuted); } @@ -148,31 +119,31 @@ namespace Umbraco.Tests.Migrations public int CountExecuted { get; set; } } - public class TestMigrationHandler : IPostMigration + public class TestPostMigration : IPostMigration { private readonly string _prodName; private readonly Args _changed; // need that one else it breaks IoC - public TestMigrationHandler() + public TestPostMigration() { _changed = new Args(); } - public TestMigrationHandler(Args changed) + public TestPostMigration(Args changed) { _changed = changed; } - public TestMigrationHandler(string prodName, Args changed) + public TestPostMigration(string prodName, Args changed) { _prodName = prodName; _changed = changed; } - public void Migrated(MigrationRunner sender, MigrationEventArgs args) + public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (_prodName.IsNullOrWhiteSpace() == false && args.ProductName != _prodName) return; + if (_prodName.IsNullOrWhiteSpace() == false && name != _prodName) return; _changed.CountExecuted++; } } diff --git a/src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs b/src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs index 76ce78882c..baff4da4af 100644 --- a/src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs +++ b/src/Umbraco.Tests/Migrations/Stubs/AlterUserTableMigrationStub.cs @@ -1,25 +1,19 @@ -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; -using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Migrations; namespace Umbraco.Tests.Migrations.Stubs { - [Migration("6.0.0", 0, "Test")] public class AlterUserTableMigrationStub : MigrationBase { public AlterUserTableMigrationStub(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { Alter.Table("umbracoUser") .AddColumn("Birthday") .AsDateTime() .Nullable(); } - - public override void Down() - { } } } diff --git a/src/Umbraco.Tests/Migrations/Stubs/DropForeignKeyMigrationStub.cs b/src/Umbraco.Tests/Migrations/Stubs/DropForeignKeyMigrationStub.cs index 2542fe8cbe..02561fb563 100644 --- a/src/Umbraco.Tests/Migrations/Stubs/DropForeignKeyMigrationStub.cs +++ b/src/Umbraco.Tests/Migrations/Stubs/DropForeignKeyMigrationStub.cs @@ -1,23 +1,16 @@ -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; -using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Migrations; namespace Umbraco.Tests.Migrations.Stubs { - [Migration("1.0.0", 0, "Test")] public class DropForeignKeyMigrationStub : MigrationBase { public DropForeignKeyMigrationStub(IMigrationContext context) : base(context) { } - public override void Up() + public override void Migrate() { Delete.ForeignKey().FromTable("umbracoUser2app").ForeignColumn("user").ToTable("umbracoUser").PrimaryColumn("id").Do(); } - - public override void Down() - { - } } } diff --git a/src/Umbraco.Tests/Migrations/Stubs/Dummy.cs b/src/Umbraco.Tests/Migrations/Stubs/Dummy.cs index 0af87b7e8a..0800390246 100644 --- a/src/Umbraco.Tests/Migrations/Stubs/Dummy.cs +++ b/src/Umbraco.Tests/Migrations/Stubs/Dummy.cs @@ -8,12 +8,7 @@ namespace Umbraco.Tests.Migrations.Stubs /// public class Dummy : IMigration { - public void Up() - { - throw new System.NotImplementedException(); - } - - public void Down() + public void Migrate() { throw new System.NotImplementedException(); } diff --git a/src/Umbraco.Tests/Migrations/Stubs/FiveZeroMigration.cs b/src/Umbraco.Tests/Migrations/Stubs/FiveZeroMigration.cs index d5d9e8a00a..f69862610f 100644 --- a/src/Umbraco.Tests/Migrations/Stubs/FiveZeroMigration.cs +++ b/src/Umbraco.Tests/Migrations/Stubs/FiveZeroMigration.cs @@ -1,24 +1,14 @@ -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; -using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Migrations; namespace Umbraco.Tests.Migrations.Stubs { - [Migration("5.0.0", 0, "Test")] public class FiveZeroMigration : MigrationBase { public FiveZeroMigration(IMigrationContext context) : base(context) { } - - public override void Up() - { - } - - public override void Down() - { - } - + public override void Migrate() + { } } } diff --git a/src/Umbraco.Tests/Migrations/Stubs/FourElevenMigration.cs b/src/Umbraco.Tests/Migrations/Stubs/FourElevenMigration.cs index 6dc4e895bb..fb1d905c0b 100644 --- a/src/Umbraco.Tests/Migrations/Stubs/FourElevenMigration.cs +++ b/src/Umbraco.Tests/Migrations/Stubs/FourElevenMigration.cs @@ -1,10 +1,7 @@ -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; -using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Migrations; namespace Umbraco.Tests.Migrations.Stubs { - [Migration("4.11.0", 0, "Test")] public class FourElevenMigration : MigrationBase { public FourElevenMigration(IMigrationContext context) @@ -12,16 +9,9 @@ namespace Umbraco.Tests.Migrations.Stubs { } - public override void Up() + public override void Migrate() { Alter.Table("umbracoUser").AddColumn("companyPhone").AsString(255); } - - public override void Down() - { - Alter.Table("umbracoUser").AlterColumn("regularPhone").AsString(255); - } - - } } diff --git a/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration1.cs b/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration1.cs index 23358e8eab..d3bdc48cbf 100644 --- a/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration1.cs +++ b/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration1.cs @@ -1,10 +1,7 @@ -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; -using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Migrations; namespace Umbraco.Tests.Migrations.Stubs { - [Migration("6.0.0", 1, "Test")] public class SixZeroMigration1 : MigrationBase { public SixZeroMigration1(IMigrationContext context) @@ -12,14 +9,9 @@ namespace Umbraco.Tests.Migrations.Stubs { } - public override void Up() + public override void Migrate() { Alter.Table("umbracoUser").AddColumn("secret").AsString(255); } - - public override void Down() - { - Alter.Table("umbracoUser").AlterColumn("passwordTip").AsString(100); - } } } diff --git a/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration2.cs b/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration2.cs index f2abc65fc4..ed3f7b29ea 100644 --- a/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration2.cs +++ b/src/Umbraco.Tests/Migrations/Stubs/SixZeroMigration2.cs @@ -1,10 +1,7 @@ -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; -using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Migrations; namespace Umbraco.Tests.Migrations.Stubs { - [Migration("6.0.0", 2, "Test")] public class SixZeroMigration2 : MigrationBase { public SixZeroMigration2(IMigrationContext context) @@ -12,16 +9,9 @@ namespace Umbraco.Tests.Migrations.Stubs { } - public override void Up() + public override void Migrate() { Alter.Table("umbracoUser").AddColumn("secondEmail").AsString(255); } - - public override void Down() - { - Alter.Table("umbracoUser").AlterColumn("sendEmail").AsBoolean(); - } - - } } diff --git a/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs deleted file mode 100644 index fc241aa4e8..0000000000 --- a/src/Umbraco.Tests/Migrations/Upgrades/BaseUpgradeTest.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Text.RegularExpressions; -using Moq; -using NPoco; -using NUnit.Framework; -using Semver; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; -using Umbraco.Core.Migrations.Install; -using Umbraco.Core.Persistence; -using Umbraco.Core.Scoping; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.Migrations.Upgrades -{ - [TestFixture] - public abstract class BaseUpgradeTest - { - /// Regular expression that finds multiline block comments. - private static readonly Regex FindComments = new Regex(@"\/\*.*?\*\/", RegexOptions.Singleline | RegexOptions.Compiled); - - [SetUp] - public virtual void Initialize() - { - TestHelper.InitializeContentDirectories(); - - Path = TestHelper.CurrentAssemblyDirectory; - AppDomain.CurrentDomain.SetData("DataDirectory", Path); - - DatabaseSpecificSetUp(); - } - - [Test] - [NUnit.Framework.Ignore("remove in v8")] // fixme remove in v8 - public virtual void Can_Upgrade_From_470_To_600() - { - var configuredVersion = new SemVersion(4, 7, 0); - var targetVersion = new SemVersion(6, 0, 0); - var db = GetConfiguredDatabase(); - - //Create db schema and data from old Total.sql file for Sql Ce - var statements = GetDatabaseSpecificSqlScript(); - // replace block comments by whitespace - statements = FindComments.Replace(statements, " "); - // execute all non-empty statements - foreach (var statement in statements.Split(";".ToCharArray())) - { - var rawStatement = statement.Replace("GO", "").Trim(); - if (rawStatement.Length > 0) - db.Execute(new Sql(rawStatement)); - } - - var logger = Mock.Of(); - - //Setup the MigrationRunner - var migrationRunner = new MigrationRunner( - Mock.Of(), - Mock.Of(), - Mock.Of(), - logger, - configuredVersion, - targetVersion, - Constants.System.UmbracoMigrationName - //pass in explicit migrations - // fixme - all gone in v8 - migrations need to be refactored anyways - //new Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero.RemoveUmbracoAppConstraints(context), - //new DeleteAppTables(context), - //new EnsureAppsTreesUpdated(context), - //new MoveMasterContentTypeData(context), - //new NewCmsContentType2ContentTypeTable(context), - //new RemoveMasterContentTypeColumn(context), - //new RenameCmsTabTable(context), - //new RenameTabIdColumn(context), - //new UpdateCmsContentTypeAllowedContentTypeTable(context), - //new UpdateCmsContentTypeTable(context), - //new UpdateCmsContentVersionTable(context), - //new UpdateCmsPropertyTypeGroupTable(context) - ); - - var upgraded = migrationRunner.Execute(/*true*/); - - Assert.That(upgraded, Is.True); - - var schemaHelper = new DatabaseSchemaCreator(db, logger); - - var hasTabTable = schemaHelper.TableExists("cmsTab"); - var hasPropertyTypeGroupTable = schemaHelper.TableExists("cmsPropertyTypeGroup"); - var hasAppTreeTable = schemaHelper.TableExists("umbracoAppTree"); - - Assert.That(hasTabTable, Is.False); - Assert.That(hasPropertyTypeGroupTable, Is.True); - Assert.That(hasAppTreeTable, Is.False); - } - - [TearDown] - public virtual void TearDown() - { - TestHelper.CleanContentDirectories(); - - Path = TestHelper.CurrentAssemblyDirectory; - AppDomain.CurrentDomain.SetData("DataDirectory", null); - - DatabaseSpecificTearDown(); - } - - public string Path { get; set; } - public abstract void DatabaseSpecificSetUp(); - public abstract void DatabaseSpecificTearDown(); - public abstract IUmbracoDatabase GetConfiguredDatabase(); - public abstract string GetDatabaseSpecificSqlScript(); - } -} diff --git a/src/Umbraco.Tests/Migrations/Upgrades/MySqlUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/MySqlUpgradeTest.cs deleted file mode 100644 index a8fbb2f3fc..0000000000 --- a/src/Umbraco.Tests/Migrations/Upgrades/MySqlUpgradeTest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Data.Common; -using Moq; -using NPoco; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.SqlSyntax; - -namespace Umbraco.Tests.Migrations.Upgrades -{ - [TestFixture, NUnit.Framework.Ignore("fixme - ignored test")] - public class MySqlUpgradeTest : BaseUpgradeTest - { - public override void DatabaseSpecificSetUp() - { - //TODO Create new database here - } - - public override void DatabaseSpecificTearDown() - { - //TODO Remove created database here - } - - public override IUmbracoDatabase GetConfiguredDatabase() - { - var dbProviderFactory = DbProviderFactories.GetFactory(Constants.DbProviderNames.MySql); - var sqlContext = new SqlContext(new MySqlSyntaxProvider(Mock.Of()), DatabaseType.MySQL, Mock.Of()); - return new UmbracoDatabase("Server = 169.254.120.3; Database = upgradetest; Uid = umbraco; Pwd = umbraco", sqlContext, dbProviderFactory, Mock.Of()); - } - - public override string GetDatabaseSpecificSqlScript() - { - return SqlScripts.SqlResources.MySqlTotal_480; - } - } -} diff --git a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs deleted file mode 100644 index 7cdd258c33..0000000000 --- a/src/Umbraco.Tests/Migrations/Upgrades/SqlCeUpgradeTest.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Configuration; -using System.Data.Common; -using System.Data.SqlServerCe; -using System.IO; -using Moq; -using NPoco; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.Migrations.Upgrades -{ - [TestFixture] - public class SqlCeUpgradeTest : BaseUpgradeTest - { - public override void DatabaseSpecificSetUp() - { - string filePath = string.Concat(Path, "\\UmbracoNPocoTests.sdf"); - - // no more "clear database" just recreate it - if (File.Exists(filePath)) File.Delete(filePath); - - if (!File.Exists(filePath)) - { - try - { - //Delete database file before continueing - if (File.Exists(filePath)) - { - File.Delete(filePath); - } - } - catch (Exception) - { - //if this doesn't work we have to make sure everything is reset! otherwise - // well run into issues because we've already set some things up - TearDown(); - throw; - } - - //Create the Sql CE database - //Get the connectionstring settings from config - var settings = ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName]; - using (var engine = new SqlCeEngine(settings.ConnectionString)) - { - engine.CreateDatabase(); - } - } - else - { - //TestHelper.ClearDatabase(); - } - - } - - public override void DatabaseSpecificTearDown() - { - //legacy API database connection close - //SqlCeContextGuardian.CloseBackgroundConnection(); - - //TestHelper.ClearDatabase(); - } - - public override IUmbracoDatabase GetConfiguredDatabase() - { - var dbProviderFactory = DbProviderFactories.GetFactory(Constants.DbProviderNames.SqlCe); - var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); - return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoNPocoTests.sdf;Flush Interval=1;", sqlContext, dbProviderFactory, Mock.Of()); - } - - public override string GetDatabaseSpecificSqlScript() - { - return SqlScripts.SqlResources.SqlCeTotal_480; - } - } -} diff --git a/src/Umbraco.Tests/Migrations/Upgrades/SqlServerUpgradeTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/SqlServerUpgradeTest.cs deleted file mode 100644 index a6daf041c7..0000000000 --- a/src/Umbraco.Tests/Migrations/Upgrades/SqlServerUpgradeTest.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Data.Common; -using Moq; -using NPoco; -using NUnit.Framework; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Core.Scoping; - -namespace Umbraco.Tests.Migrations.Upgrades -{ - [TestFixture, NUnit.Framework.Ignore("fixme - ignored test")] - public class SqlServerUpgradeTest : BaseUpgradeTest - { - public override void DatabaseSpecificSetUp() - { } - - public override void DatabaseSpecificTearDown() - { } - - public override IUmbracoDatabase GetConfiguredDatabase() - { - var dbProviderFactory = DbProviderFactories.GetFactory("System.Data.SqlClient"); - var sqlContext = new SqlContext(new SqlServerSyntaxProvider(new Lazy(() => null)), DatabaseType.SqlServer2008, Mock.Of()); - return new UmbracoDatabase(@"server=.\SQLEXPRESS;database=EmptyForTest;user id=umbraco;password=umbraco", sqlContext, dbProviderFactory, Mock.Of()); - } - - public override string GetDatabaseSpecificSqlScript() - { - return SqlScripts.SqlResources.SqlServerTotal_480; - } - } -} diff --git a/src/Umbraco.Tests/Migrations/Upgrades/ValidateOlderSchemaTest.cs b/src/Umbraco.Tests/Migrations/Upgrades/ValidateOlderSchemaTest.cs deleted file mode 100644 index efc0ceeeed..0000000000 --- a/src/Umbraco.Tests/Migrations/Upgrades/ValidateOlderSchemaTest.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Configuration; -using System.Data.Common; -using System.Data.SqlServerCe; -using System.IO; -using System.Text.RegularExpressions; -using Moq; -using NPoco; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations.Install; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.Migrations.Upgrades -{ - [TestFixture] - [NUnit.Framework.Ignore("does not apply to v8")] // fixme - remove - public class ValidateOlderSchemaTest - { - /// Regular expression that finds multiline block comments. - private static readonly Regex FindComments = new Regex(@"\/\*.*?\*\/", RegexOptions.Singleline | RegexOptions.Compiled); - - [Test] - public virtual void DatabaseSchemaCreation_Returns_DatabaseSchemaResult_Where_DetermineInstalledVersion_Is_4_7_0() - { - // Arrange - var db = GetConfiguredDatabase(); - var schema = new DatabaseSchemaCreator(db, Mock.Of()); - - //Create db schema and data from old Total.sql file for Sql Ce - string statements = GetDatabaseSpecificSqlScript(); - // replace block comments by whitespace - statements = FindComments.Replace(statements, " "); - // execute all non-empty statements - foreach (string statement in statements.Split(";".ToCharArray())) - { - string rawStatement = statement.Replace("GO", "").Trim(); - if (rawStatement.Length > 0) - db.Execute(new Sql(rawStatement)); - } - - // Act - var result = schema.ValidateSchema(); - - // Assert - var expected = new Version(4, 7, 0); - Assert.AreEqual(expected, result.DetermineInstalledVersion()); - } - - [SetUp] - public virtual void Initialize() - { - TestHelper.InitializeContentDirectories(); - - Path = TestHelper.CurrentAssemblyDirectory; - AppDomain.CurrentDomain.SetData("DataDirectory", Path); - - //Delete database file before continueing - string filePath = string.Concat(Path, "\\UmbracoNPocoTests.sdf"); - if (File.Exists(filePath)) - { - File.Delete(filePath); - } - - //Get the connectionstring settings from config - var settings = ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName]; - - //Create the Sql CE database - using (var engine = new SqlCeEngine(settings.ConnectionString)) - { - engine.CreateDatabase(); - } - - } - - [TearDown] - public virtual void TearDown() - { - TestHelper.CleanContentDirectories(); - - Path = TestHelper.CurrentAssemblyDirectory; - AppDomain.CurrentDomain.SetData("DataDirectory", null); - - //legacy API database connection close - //SqlCeContextGuardian.CloseBackgroundConnection(); - - string filePath = string.Concat(Path, "\\UmbracoNPocoTests.sdf"); - if (File.Exists(filePath)) - { - File.Delete(filePath); - } - } - - public string Path { get; set; } - - public IUmbracoDatabase GetConfiguredDatabase() - { - var dbProviderFactory = DbProviderFactories.GetFactory(Constants.DbProviderNames.SqlCe); - var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); - return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoNPocoTests.sdf;Flush Interval=1;", sqlContext, dbProviderFactory, Mock.Of()); - } - - public string GetDatabaseSpecificSqlScript() - { - return SqlScripts.SqlResources.SqlCeTotal_480; - } - } -} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 02ccb9bb97..8f2975f2a4 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -224,6 +224,8 @@ + + @@ -235,7 +237,6 @@ - @@ -331,7 +332,6 @@ - @@ -450,8 +450,6 @@ - - True True @@ -460,10 +458,6 @@ - - - - diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 5892f4096d..43e970b1e3 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -116,9 +116,6 @@ namespace Umbraco.Web.Composing public static ActionCollection Actions => Container.GetInstance(); - public static MigrationCollectionBuilder MigrationCollectionBuilder - => Container.GetInstance(); - public static ContentFinderCollection ContentFinders => Container.GetInstance(); diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index cad77c35ce..a0c86f066c 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -52,7 +52,7 @@ namespace Umbraco.Web.Install new ConfigureMachineKey(), new DatabaseConfigureStep(_databaseBuilder), new DatabaseInstallStep(_databaseBuilder, Current.RuntimeState, Current.Logger), - new DatabaseUpgradeStep(_databaseBuilder, Current.Services.MigrationEntryService, Current.RuntimeState, Current.MigrationCollectionBuilder, Current.Logger), + new DatabaseUpgradeStep(_databaseBuilder, Current.RuntimeState, Current.Logger), new StarterKitDownloadStep(Current.Services.ContentService, this, Current.UmbracoContext.Security), new StarterKitInstallStep(_httpContext), new StarterKitCleanupStep(), diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs index bb1584006a..c078caf906 100644 --- a/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs @@ -1,13 +1,9 @@ using System; -using System.Collections.Generic; using System.Configuration; using System.Linq; using Umbraco.Core; -using Umbraco.Core.Configuration; using Umbraco.Core.Logging; -using Umbraco.Core.Migrations; using Umbraco.Core.Migrations.Install; -using Umbraco.Core.Services; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps @@ -17,17 +13,13 @@ namespace Umbraco.Web.Install.InstallSteps internal class DatabaseUpgradeStep : InstallSetupStep { private readonly DatabaseBuilder _databaseBuilder; - private readonly IMigrationEntryService _migrationEntryService; private readonly IRuntimeState _runtime; private readonly ILogger _logger; - private readonly MigrationCollectionBuilder _migrationCollectionBuilder; - public DatabaseUpgradeStep(DatabaseBuilder databaseBuilder, IMigrationEntryService migrationEntryService, IRuntimeState runtime, MigrationCollectionBuilder migrationCollectionBuilder, ILogger logger) + public DatabaseUpgradeStep(DatabaseBuilder databaseBuilder, IRuntimeState runtime, ILogger logger) { _databaseBuilder = databaseBuilder; - _migrationEntryService = migrationEntryService; _runtime = runtime; - _migrationCollectionBuilder = migrationCollectionBuilder; _logger = logger; } @@ -41,7 +33,7 @@ namespace Umbraco.Web.Install.InstallSteps { _logger.Info("Running 'Upgrade' service"); - var result = _databaseBuilder.UpgradeSchemaAndData(_migrationEntryService, _migrationCollectionBuilder); + var result = _databaseBuilder.UpgradeSchemaAndData(); if (result.Success == false) { diff --git a/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs b/src/Umbraco.Web/Migrations/ClearCsrfCookiesAfterUpgrade.cs similarity index 65% rename from src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs rename to src/Umbraco.Web/Migrations/ClearCsrfCookiesAfterUpgrade.cs index c2c224a5a2..efa788d4f4 100644 --- a/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs +++ b/src/Umbraco.Web/Migrations/ClearCsrfCookiesAfterUpgrade.cs @@ -1,20 +1,21 @@ using System.Web; -using Umbraco.Core.Events; -using Umbraco.Web.WebApi.Filters; +using Semver; using Umbraco.Core; -using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Migrations; +using Umbraco.Core.Scoping; +using Umbraco.Web.WebApi.Filters; -namespace Umbraco.Web.Strategies.Migrations +namespace Umbraco.Web.Migrations { /// /// After upgrade we clear out the csrf tokens /// public class ClearCsrfCookiesAfterUpgrade : IPostMigration { - public void Migrated(MigrationRunner sender, MigrationEventArgs args) + public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (args.ProductName != Constants.System.UmbracoMigrationName) return; + if (name != Constants.System.UmbracoUpgraderName) return; if (HttpContext.Current == null) return; var http = new HttpContextWrapper(HttpContext.Current); diff --git a/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs b/src/Umbraco.Web/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs similarity index 76% rename from src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs rename to src/Umbraco.Web/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs index bfca607e78..2ce2f3334a 100644 --- a/src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs +++ b/src/Umbraco.Web/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs @@ -1,10 +1,10 @@ using Semver; using Umbraco.Core; -using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Migrations; +using Umbraco.Core.Scoping; -namespace Umbraco.Web.Strategies.Migrations +namespace Umbraco.Web.Migrations { /// /// This will execute after upgrading to remove any xml cache for media that are currently in the bin @@ -23,25 +23,25 @@ namespace Umbraco.Web.Strategies.Migrations _logger = logger; } - public void Migrated(MigrationRunner sender, MigrationEventArgs args) + public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (args.ProductName != Constants.System.UmbracoMigrationName) return; + if (name != Constants.System.UmbracoUpgraderName) return; var target70 = new SemVersion(7 /*, 0, 0*/); - if (args.ConfiguredSemVersion <= target70) + if (originVersion <= target70) { //This query is structured to work with MySql, SQLCE and SqlServer: // http://issues.umbraco.org/issue/U4-3876 - var syntax = args.MigrationContext.SqlContext.SqlSyntax; + var syntax = scope.SqlContext.SqlSyntax; var sql = @"DELETE FROM cmsContentXml WHERE nodeId IN (SELECT nodeId FROM (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml INNER JOIN umbracoNode ON cmsContentXml.nodeId = umbracoNode.id WHERE nodeObjectType = '" + Constants.ObjectTypes.Media + "' AND " + syntax.GetQuotedColumnName("path") + " LIKE '%-21%') x)"; - var count = args.MigrationContext.Database.Execute(sql); + var count = scope.Database.Execute(sql); _logger.Info("Cleared " + count + " items from the media xml cache that were trashed and not meant to be there"); } diff --git a/src/Umbraco.Web/Migrations/EnsureListViewDataTypeIsCreated.cs b/src/Umbraco.Web/Migrations/EnsureListViewDataTypeIsCreated.cs new file mode 100644 index 0000000000..67ea5b1542 --- /dev/null +++ b/src/Umbraco.Web/Migrations/EnsureListViewDataTypeIsCreated.cs @@ -0,0 +1,88 @@ +using System; +using NPoco; +using Semver; +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Migrations; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Scoping; + +namespace Umbraco.Web.Migrations +{ + /// + /// Creates the built in list view data types + /// + public class EnsureDefaultListViewDataTypesCreated : IPostMigration + { + public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) + { + if (name != Constants.System.UmbracoUpgraderName) return; + + var target720 = new SemVersion(7, 2, 0); + + if (originVersion > target720) + return; + + var syntax = scope.SqlContext.SqlSyntax; + + try + { + //Turn on identity insert if db provider is not mysql + if (syntax.SupportsIdentityInsert()) + scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", syntax.GetQuotedTableName("umbracoNode")))); + + if (scope.Database.Exists(Constants.DataTypes.DefaultContentListView)) + { + //If this already exists then just exit + return; + } + + scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-95", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMediaListView, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-96", SortOrder = 2, UniqueId = new Guid("3A0156C4-3B8C-4803-BDC1-6871FAA83FFF"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + scope.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMembersListView, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-97", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + } + finally + { + //Turn off identity insert if db provider is not mysql + if (syntax.SupportsIdentityInsert()) + scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", syntax.GetQuotedTableName("umbracoNode")))); + } + + try + { + //Turn on identity insert if db provider is not mysql + if (syntax.SupportsIdentityInsert()) + scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", syntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.DataType)))); + + scope.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.DataTypes.DefaultContentListView, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); + scope.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -27, DataTypeId = Constants.DataTypes.DefaultMediaListView, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); + scope.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.DataTypes.DefaultMembersListView, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); + } + finally + { + //Turn off identity insert if db provider is not mysql + if (syntax.SupportsIdentityInsert()) + scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", syntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.DataType)))); + } + + try + { + //Turn on identity insert if db provider is not mysql + if (syntax.SupportsIdentityInsert()) + scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", syntax.GetQuotedTableName("cmsDataTypePreValues")))); + + //defaults for the member list + scope.Database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -1, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.DataTypes.DefaultMembersListView, Value = "10" }); + scope.Database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.DataTypes.DefaultMembersListView, Value = "Name" }); + scope.Database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -3, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.DataTypes.DefaultMembersListView, Value = "asc" }); + scope.Database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -4, Alias = "includeProperties", SortOrder = 4, DataTypeNodeId = Constants.DataTypes.DefaultMembersListView, Value = "[{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]" }); + } + finally + { + //Turn off identity insert if db provider is not mysql + if (syntax.SupportsIdentityInsert()) + scope.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", syntax.GetQuotedTableName("cmsDataTypePreValues")))); + } + } + } +} diff --git a/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs b/src/Umbraco.Web/Migrations/OverwriteStylesheetFilesFromTempFiles.cs similarity index 76% rename from src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs rename to src/Umbraco.Web/Migrations/OverwriteStylesheetFilesFromTempFiles.cs index e99fdf4a36..63a97befe8 100644 --- a/src/Umbraco.Web/Strategies/Migrations/OverwriteStylesheetFilesFromTempFiles.cs +++ b/src/Umbraco.Web/Migrations/OverwriteStylesheetFilesFromTempFiles.cs @@ -1,14 +1,13 @@ -using System; -using System.IO; +using System.IO; using Semver; -using Umbraco.Core.Events; using Umbraco.Core; -using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Migrations; +using Umbraco.Core.Migrations.Upgrade; +using Umbraco.Core.Scoping; -namespace Umbraco.Web.Strategies.Migrations +namespace Umbraco.Web.Migrations { /// @@ -18,13 +17,13 @@ namespace Umbraco.Web.Strategies.Migrations /// public sealed class OverwriteStylesheetFilesFromTempFiles : IPostMigration { - public void Migrated(MigrationRunner sender, MigrationEventArgs args) + public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (args.ProductName != Constants.System.UmbracoMigrationName) return; + if (name != Constants.System.UmbracoUpgraderName) return; var target73 = new SemVersion(7, 3, 0); - if (args.ConfiguredSemVersion <= target73) + if (originVersion <= target73) { var tempCssFolder = IOHelper.MapPath("~/App_Data/TEMP/CssMigration/"); var cssFolder = IOHelper.MapPath("~/css"); @@ -39,7 +38,7 @@ namespace Umbraco.Web.Strategies.Migrations { //backup var targetPath = Path.Combine(tempCssFolder, relativePath.EnsureEndsWith(".bak")); - args.MigrationContext.Logger.Info("CSS file is being backed up from {0}, to {1} before being migrated to new format", () => cssFilePath, () => targetPath); + logger.Info("CSS file is being backed up from {0}, to {1} before being migrated to new format", () => cssFilePath, () => targetPath); File.Copy(cssFilePath, targetPath, true); } diff --git a/src/Umbraco.Web/Strategies/Migrations/RebuildXmlCachesAfterUpgrade.cs b/src/Umbraco.Web/Migrations/RebuildXmlCachesAfterUpgrade.cs similarity index 76% rename from src/Umbraco.Web/Strategies/Migrations/RebuildXmlCachesAfterUpgrade.cs rename to src/Umbraco.Web/Migrations/RebuildXmlCachesAfterUpgrade.cs index e9ab382f9f..92774325ee 100644 --- a/src/Umbraco.Web/Strategies/Migrations/RebuildXmlCachesAfterUpgrade.cs +++ b/src/Umbraco.Web/Migrations/RebuildXmlCachesAfterUpgrade.cs @@ -1,14 +1,13 @@ using System; -using umbraco; +using Semver; using Umbraco.Core; -using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Migrations; -using Umbraco.Core.Services; +using Umbraco.Core.Scoping; using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache.XmlPublishedCache; -using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings; -namespace Umbraco.Web.Strategies.Migrations +namespace Umbraco.Web.Migrations { /// /// Rebuilds the Xml caches after upgrading. @@ -23,14 +22,14 @@ namespace Umbraco.Web.Strategies.Migrations /// public class RebuildXmlCachesAfterUpgrade : IPostMigration { - public void Migrated(MigrationRunner sender, MigrationEventArgs args) + public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (args.ProductName != Constants.System.UmbracoMigrationName) return; + if (name != Constants.System.UmbracoUpgraderName) return; - var v730 = new Semver.SemVersion(new Version(7, 3, 0)); + var v730 = new SemVersion(new Version(7, 3, 0)); - var doMedia = args.ConfiguredSemVersion < v730; - var doContent = args.ConfiguredSemVersion < v730; + var doMedia = originVersion < v730; + var doContent = originVersion < v730; if (doMedia) { diff --git a/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs b/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs deleted file mode 100644 index 279a8f8119..0000000000 --- a/src/Umbraco.Web/Strategies/Migrations/EnsureListViewDataTypeIsCreated.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using NPoco; -using Semver; -using Umbraco.Core; -using Umbraco.Core.Events; -using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Configuration; -using Umbraco.Core.Migrations; - -namespace Umbraco.Web.Strategies.Migrations -{ - /// - /// Creates the built in list view data types - /// - public class EnsureDefaultListViewDataTypesCreated : IPostMigration - { - public void Migrated(MigrationRunner sender, MigrationEventArgs args) - { - if (args.ProductName != Constants.System.UmbracoMigrationName) return; - - var target720 = new SemVersion(7, 2, 0); - - if (args.ConfiguredSemVersion <= target720) - { - EnsureListViewDataTypeCreated(args); - - } - } - - private void EnsureListViewDataTypeCreated(MigrationEventArgs e) - { - var syntax = e.MigrationContext.SqlContext.SqlSyntax; - - using (var transaction = e.MigrationContext.Database.GetTransaction()) - { - try - { - //Turn on identity insert if db provider is not mysql - if (syntax.SupportsIdentityInsert()) - e.MigrationContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", syntax.GetQuotedTableName("umbracoNode")))); - - if (e.MigrationContext.Database.Exists(Constants.DataTypes.DefaultContentListView)) - { - //If this already exists then just exit - return; - } - - e.MigrationContext.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-95", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - e.MigrationContext.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMediaListView, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-96", SortOrder = 2, UniqueId = new Guid("3A0156C4-3B8C-4803-BDC1-6871FAA83FFF"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - e.MigrationContext.Database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMembersListView, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-97", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - } - finally - { - //Turn off identity insert if db provider is not mysql - if (syntax.SupportsIdentityInsert()) - e.MigrationContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", syntax.GetQuotedTableName("umbracoNode")))); - } - - - try - { - //Turn on identity insert if db provider is not mysql - if (syntax.SupportsIdentityInsert()) - e.MigrationContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", syntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.DataType)))); - - e.MigrationContext.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.DataTypes.DefaultContentListView, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); - e.MigrationContext.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -27, DataTypeId = Constants.DataTypes.DefaultMediaListView, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); - e.MigrationContext.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.DataTypes.DefaultMembersListView, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); - } - finally - { - //Turn off identity insert if db provider is not mysql - if (syntax.SupportsIdentityInsert()) - e.MigrationContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", syntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.DataType)))); - } - - - - try - { - //Turn on identity insert if db provider is not mysql - if (syntax.SupportsIdentityInsert()) - e.MigrationContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} ON ", syntax.GetQuotedTableName("cmsDataTypePreValues")))); - - //defaults for the member list - e.MigrationContext.Database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -1, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.DataTypes.DefaultMembersListView, Value = "10" }); - e.MigrationContext.Database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.DataTypes.DefaultMembersListView, Value = "Name" }); - e.MigrationContext.Database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -3, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.DataTypes.DefaultMembersListView, Value = "asc" }); - e.MigrationContext.Database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -4, Alias = "includeProperties", SortOrder = 4, DataTypeNodeId = Constants.DataTypes.DefaultMembersListView, Value = "[{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]" }); - } - finally - { - //Turn off identity insert if db provider is not mysql - if (syntax.SupportsIdentityInsert()) - e.MigrationContext.Database.Execute(new Sql(string.Format("SET IDENTITY_INSERT {0} OFF;", syntax.GetQuotedTableName("cmsDataTypePreValues")))); - } - - - - transaction.Complete(); - } - } - - } - -} diff --git a/src/Umbraco.Web/Strategies/Migrations/IPostMigration.cs b/src/Umbraco.Web/Strategies/Migrations/IPostMigration.cs deleted file mode 100644 index 4823aebf59..0000000000 --- a/src/Umbraco.Web/Strategies/Migrations/IPostMigration.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Umbraco.Core.Events; -using Umbraco.Core.Migrations; - -namespace Umbraco.Web.Strategies.Migrations -{ - public interface IPostMigration - { - void Migrated(MigrationRunner runner, MigrationEventArgs args); - } -} diff --git a/src/Umbraco.Web/Strategies/Migrations/PostMigrationComponent.cs b/src/Umbraco.Web/Strategies/Migrations/PostMigrationComponent.cs deleted file mode 100644 index 6111027007..0000000000 --- a/src/Umbraco.Web/Strategies/Migrations/PostMigrationComponent.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Umbraco.Core.Components; -using Umbraco.Core.Composing; -using LightInject; -using Umbraco.Core.Migrations; - -namespace Umbraco.Web.Strategies.Migrations -{ - public class PostMigrationComponent : UmbracoComponentBase, IUmbracoCoreComponent - { - public override void Compose(Composition composition) - { - composition.Container.RegisterCollectionBuilder() - .Add(factory => factory.GetInstance().GetTypes()); - } - - public void Initialize(PostMigrationCollection posts) - { - // whatever the runtime level, ie also when installing or upgrading - - foreach (var post in posts) - MigrationRunner.Migrated += post.Migrated; - } - } - - public static class PostMigrationComponentCompositionExtensions - { - /// - /// Gets the post-migrations collection builder. - /// - /// The composition. - internal static PostMigrationCollectionBuilder PostMigrations(this Composition composition) - => composition.Container.GetInstance(); - } -} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 2be382d88c..d027321617 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -322,10 +322,6 @@ - - - - @@ -705,10 +701,10 @@ - - - - + + + + @@ -901,7 +897,7 @@ Resources.resx - +