diff --git a/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs b/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs index c9a536f0ce..e3d7bca07d 100644 --- a/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs +++ b/src/Umbraco.Core/Composing/CompositionRoots/ServicesCompositionRoot.cs @@ -27,7 +27,6 @@ namespace Umbraco.Core.Composing.CompositionRoots // register the services container.RegisterSingleton(); - 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 9438e4590e..8ab2f74f4c 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 UmbracoUpgraderName = "Umbraco.Core"; + public const string UmbracoUpgradePlanName = "Umbraco.Core"; } } } diff --git a/src/Umbraco.Core/CoreRuntime.cs b/src/Umbraco.Core/CoreRuntime.cs index 32942b1ff5..af0862c9aa 100644 --- a/src/Umbraco.Core/CoreRuntime.cs +++ b/src/Umbraco.Core/CoreRuntime.cs @@ -12,13 +12,13 @@ using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; -using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; namespace Umbraco.Core { @@ -176,7 +176,9 @@ namespace Umbraco.Core } } - /// + /// + /// Composes the runtime. + /// public virtual void Compose(ServiceContainer container) { // compose the very essential things that are needed to bootstrap, before anything else, @@ -252,7 +254,7 @@ namespace Umbraco.Core { // there *is* a local version, but it does not match the code version // need to upgrade - logger.Debug($"Local version \"{localVersion}\" != code version, need to upgrade Umbraco."); + logger.Debug($"Local version \"{localVersion}\" != code version \"{codeVersion}\", need to upgrade Umbraco."); runtimeState.Level = RuntimeLevel.Upgrade; } else if (databaseFactory.Configured == false) @@ -297,16 +299,15 @@ namespace Umbraco.Core // else // look for a matching migration entry - bypassing services entirely - they are not 'up' yet // fixme - in a LB scenario, ensure that the DB gets upgraded only once! - // fixme - eventually move to yol-style guid-based transitions bool exists; try { - exists = EnsureMigration(databaseFactory, codeVersion); + exists = EnsureUmbracoUpgradeState(databaseFactory, logger); } catch { // can connect to the database but cannot access the migration table... need to install - logger.Debug("Could not check migrations, need to install Umbraco."); + logger.Debug("Could not check the upgrade state, need to install Umbraco."); runtimeState.Level = RuntimeLevel.Install; return; } @@ -323,21 +324,30 @@ namespace Umbraco.Core // although the files version matches the code version, the database version does not // which means the local files have been upgraded but not the database - need to upgrade - logger.Debug("Database migrations have not executed, need to upgrade Umbraco."); + logger.Debug("Has not reached the final upgrade step, need to upgrade Umbraco."); runtimeState.Level = RuntimeLevel.Upgrade; } - protected virtual bool EnsureMigration(IUmbracoDatabaseFactory databaseFactory, SemVersion codeVersion) + protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) { - using (var database = databaseFactory.CreateDatabase()) // no scope - just the database + // no scope, no key value service - just directly accessing the database + + string state; + using (var database = databaseFactory.CreateDatabase()) { - var codeVersionString = codeVersion.ToString(); var sql = databaseFactory.SqlContext.Sql() - .Select() - .From() - .Where(x => x.Name.InvariantEquals(Constants.System.UmbracoUpgraderName) && x.Version == codeVersionString); - return database.FirstOrDefault(sql) != null; + .Select() + .From() + .Where(x => x.Key == "Umbraco.Core.Upgrader.State+Umbraco.Core"); + state = database.FirstOrDefault(sql)?.Value; } + + var umbracoPlan = new UmbracoPlan(); + var finalState = umbracoPlan.Validate(); + + logger.Debug($"Final upgrade state is \"{finalState}\", database contains \"{state ?? ""}\"."); + + return state == finalState; } private static string LocalVersion diff --git a/src/Umbraco.Core/CoreRuntimeComponent.cs b/src/Umbraco.Core/CoreRuntimeComponent.cs index 5352a66ca5..0e9d8cb0c6 100644 --- a/src/Umbraco.Core/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/CoreRuntimeComponent.cs @@ -121,6 +121,8 @@ namespace Umbraco.Core composition.Container.RegisterCollectionBuilder() .Add(factory => factory.GetInstance().GetTypes()); + composition.Container.RegisterSingleton(); + // by default, register a noop factory composition.Container.RegisterSingleton(); } diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs index 780df8c205..1296c86992 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.UmbracoUpgraderName, + Name = Constants.System.UmbracoUpgradePlanName, 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 7274fb5c56..41184c4471 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaResult.cs @@ -2,11 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Semver; using Umbraco.Core.Configuration; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Core.Services; namespace Umbraco.Core.Migrations.Install { @@ -39,24 +37,6 @@ namespace Umbraco.Core.Migrations.Install internal IEnumerable DbIndexDefinitions { get; set; } - /// - /// Checks in the db which version is installed based on the migrations that have been run - /// - /// - /// - public SemVersion DetermineInstalledVersionByMigrations(IMigrationEntryService migrationEntryService) - { - SemVersion mostrecent = null; - - if (ValidTables.Any(x => x.InvariantEquals("umbracoMigration"))) - { - var allMigrations = migrationEntryService.GetAll(Constants.System.UmbracoUpgraderName); - mostrecent = allMigrations.OrderByDescending(x => x.Version).Select(x => x.Version).FirstOrDefault(); - } - - return mostrecent ?? new SemVersion(new Version(0, 0, 0)); - } - /// /// Determines the version of the currently installed database by detecting the current database structure /// diff --git a/src/Umbraco.Core/Migrations/MigrationPlan.cs b/src/Umbraco.Core/Migrations/MigrationPlan.cs index d9f5845311..80775cd5d3 100644 --- a/src/Umbraco.Core/Migrations/MigrationPlan.cs +++ b/src/Umbraco.Core/Migrations/MigrationPlan.cs @@ -9,25 +9,32 @@ 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) + // initializes a non-executing plan + public MigrationPlan(string name) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name)); - _name = name; - _scopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider)); + Name = name; + } + + // initializes a plan + public MigrationPlan(string name, IMigrationBuilder migrationBuilder, ILogger logger) + { + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name)); + Name = name; _migrationBuilder = migrationBuilder ?? throw new ArgumentNullException(nameof(migrationBuilder)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } + public string Name { get; } + public MigrationPlan Add(string sourceState, string targetState) - => Add(sourceState, targetState); + => Add(sourceState, targetState); public MigrationPlan Add(string sourceState, string targetState) where TMigration : IMigration @@ -70,7 +77,7 @@ namespace Umbraco.Core.Migrations } public MigrationPlan Chain(string targetState) - => Chain(targetState); + => Chain(targetState); public MigrationPlan Chain(string targetState) where TMigration : IMigration @@ -85,8 +92,7 @@ namespace Umbraco.Core.Migrations return this; } - // internal for tests - internal void Validate() + public string 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 @@ -118,13 +124,18 @@ namespace Umbraco.Core.Migrations } verified.AddRange(visited); } + + return finalState; } public string Execute(IScope scope, string fromState) { Validate(); - _logger.Info("Starting \"{0}\"...", () => _name); + if (_migrationBuilder == null || _logger == null) + throw new InvalidOperationException("Cannot execute a non-executing plan."); + + _logger.Info("Starting \"{0}\"...", () => Name); var origState = fromState; //GetState(); var info = "At " + (string.IsNullOrWhiteSpace(origState) ? "origin" : ("\"" + origState + "\"")) + "."; info = info.Replace("{", "{{").Replace("}", "}}"); // stupid log4net diff --git a/src/Umbraco.Core/Migrations/NopMigration.cs b/src/Umbraco.Core/Migrations/NoopMigration.cs similarity index 73% rename from src/Umbraco.Core/Migrations/NopMigration.cs rename to src/Umbraco.Core/Migrations/NoopMigration.cs index 8a584bc6ef..7a2a7d5875 100644 --- a/src/Umbraco.Core/Migrations/NopMigration.cs +++ b/src/Umbraco.Core/Migrations/NoopMigration.cs @@ -1,6 +1,6 @@ namespace Umbraco.Core.Migrations { - public class NopMigration : IMigration + public class NoopMigration : IMigration { public void Migrate() { diff --git a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs index 24b1bd28d7..7a315d2b32 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs @@ -22,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.UmbracoUpgraderName }); + var version = database.FirstOrDefault("SELECT version FROM umbracoMigration WHERE name=@name ORDER BY version DESC", new { name = Constants.System.UmbracoUpgradePlanName }); if (version != null && version.StartsWith("7.6.0")) return; var updates = database.Query(@"SELECT umbracoNode.id, cmsTemplate.alias FROM umbracoNode diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index bcea9b643b..1583087ac7 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -4,7 +4,6 @@ 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 { @@ -13,8 +12,19 @@ namespace Umbraco.Core.Migrations.Upgrade /// public class UmbracoPlan : MigrationPlan { - public UmbracoPlan(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, ILogger logger) - : base("umbraco", scopeProvider, migrationBuilder, logger) + public UmbracoPlan() + : base(Constants.System.UmbracoUpgradePlanName) + { + DefinePlan(); + } + + public UmbracoPlan(IMigrationBuilder migrationBuilder, ILogger logger) + : base(Constants.System.UmbracoUpgradePlanName, migrationBuilder, logger) + { + DefinePlan(); + } + + private void DefinePlan() { // INSTALL // when installing, the source state is empty, and the target state should be the installed state, diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs index 411dc1c92b..e0eace850b 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoUpgrader.cs @@ -11,12 +11,12 @@ 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) + : base(scopeProvider, migrationBuilder, keyValueService, postMigrations, logger) { } protected override MigrationPlan GetPlan() { - return new UmbracoPlan(ScopeProvider, MigrationBuilder, Logger); + return new UmbracoPlan(MigrationBuilder, Logger); } protected override string GetInitialState() diff --git a/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs b/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs index a9ca8bd856..49bb3cc829 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/Upgrader.cs @@ -1,6 +1,5 @@ using System; using Semver; -using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Scoping; using Umbraco.Core.Services; @@ -11,13 +10,10 @@ namespace Umbraco.Core.Migrations.Upgrade { private readonly IKeyValueService _keyValueService; private readonly PostMigrationCollection _postMigrations; + private MigrationPlan _plan; - protected Upgrader(string name, IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations, ILogger logger) + protected Upgrader(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)); @@ -25,9 +21,9 @@ namespace Umbraco.Core.Migrations.Upgrade Logger = logger ?? throw new ArgumentNullException(nameof(logger)); } - public string Name { get; } + public string Name => Plan.Name; - public string StateValueKey { get; } + public string StateValueKey => "Umbraco.Core.Upgrader.State+" + Plan.Name; protected IScopeProvider ScopeProvider { get; } @@ -35,13 +31,15 @@ namespace Umbraco.Core.Migrations.Upgrade protected ILogger Logger { get; } + protected MigrationPlan Plan => _plan ?? (_plan = GetPlan()); + protected abstract MigrationPlan GetPlan(); protected abstract string GetInitialState(); protected abstract (SemVersion, SemVersion) GetVersions(); public void Execute() { - var plan = GetPlan(); + var plan = Plan; using (var scope = ScopeProvider.CreateScope()) { @@ -59,6 +57,8 @@ namespace Umbraco.Core.Migrations.Upgrade // execute plan var state = plan.Execute(scope, currentState); + if (string.IsNullOrWhiteSpace(state)) + throw new Exception("Plan execution returned an invalid null or empty state."); // save new state if (forceState) diff --git a/src/Umbraco.Core/Models/Rdbms/KeyValueDto.cs b/src/Umbraco.Core/Models/Rdbms/KeyValueDto.cs index a27b137d2a..c8883ef679 100644 --- a/src/Umbraco.Core/Models/Rdbms/KeyValueDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/KeyValueDto.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Models.Rdbms { [TableName(Constants.DatabaseSchema.Tables.KeyValue)] - [PrimaryKey("key")] + [PrimaryKey("key", AutoIncrement = false)] [ExplicitColumns] internal class KeyValueDto { diff --git a/src/Umbraco.Core/Services/IMigrationEntryService.cs b/src/Umbraco.Core/Services/IMigrationEntryService.cs deleted file mode 100644 index bcdfa191b9..0000000000 --- a/src/Umbraco.Core/Services/IMigrationEntryService.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using Semver; -using Umbraco.Core.Models; - -namespace Umbraco.Core.Services -{ - public interface IMigrationEntryService - { - /// - /// Creates a migration entry, will throw an exception if it already exists - /// - /// - /// - /// - IMigrationEntry CreateEntry(string migrationName, SemVersion version); - - /// - /// Finds a migration by name and version, returns null if not found - /// - /// - /// - /// - IMigrationEntry FindEntry(string migrationName, SemVersion version); - - /// - /// Gets all entries for a given migration name - /// - /// - /// - IEnumerable GetAll(string migrationName); - } -} diff --git a/src/Umbraco.Core/Services/Implement/KeyValueService.cs b/src/Umbraco.Core/Services/Implement/KeyValueService.cs index 6ecf642c7b..95d774249a 100644 --- a/src/Umbraco.Core/Services/Implement/KeyValueService.cs +++ b/src/Umbraco.Core/Services/Implement/KeyValueService.cs @@ -34,17 +34,40 @@ namespace Umbraco.Core.Services.Implement private void Initialize() { + // all this cannot be achieved via migrations since it needs to run + // before any migration, in order to figure out migrations + 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) + // assume that if the lock object exists, then everything is ok + if (scope.Database.Exists(Constants.Locks.KeyValues)) + { + scope.Complete(); + return; + } + + // drop the 'identity' on primary key + foreach (var sql in new[] + { + "alter table umbracoLock add column nid int null;", + "update umbracoLock set nid = id;", + "alter table umbracoLock drop constraint PK_umbracoLock;", + "alter table umbracoLock drop column id;", + "alter table umbracoLock add column id int null;", + "update umbracoLock set id = nid;", + "alter table umbracoLock drop column nid;", + "alter table umbracoLock alter column id int not null;", + "alter table umbracoLock add constraint PK_umbracoLock primary key (id);" + }) + scope.Database.Execute(sql); + + // insert the key-value lock + 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(); - } + // create the key-value table + var context = new MigrationContext(scope.Database, _logger); + new CreateBuilder(context).Table().Do(); scope.Complete(); } diff --git a/src/Umbraco.Core/Services/MigrationEntryService.cs b/src/Umbraco.Core/Services/MigrationEntryService.cs deleted file mode 100644 index 9602e59e4b..0000000000 --- a/src/Umbraco.Core/Services/MigrationEntryService.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Collections.Generic; -using Semver; -using Umbraco.Core.Events; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Scoping; - -namespace Umbraco.Core.Services -{ - /// - /// Manages migration entries in the database - /// - public sealed class MigrationEntryService : ScopeRepositoryService, IMigrationEntryService - { - private readonly IMigrationEntryRepository _migrationEntryRepository; - - public MigrationEntryService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, - IMigrationEntryRepository migrationEntryRepository) - : base(provider, logger, eventMessagesFactory) - { - _migrationEntryRepository = migrationEntryRepository; - } - - /// - /// Creates a migration entry, will throw an exception if it already exists - /// - /// - /// - /// - public IMigrationEntry CreateEntry(string migrationName, SemVersion version) - { - var entry = new MigrationEntry - { - MigrationName = migrationName, - Version = version - }; - - using (var scope = ScopeProvider.CreateScope()) - { - _migrationEntryRepository.Save(entry); - scope.Complete(); - } - - return entry; - } - - /// - /// Finds a migration by name and version, returns null if not found - /// - /// - /// - /// - public IMigrationEntry FindEntry(string migrationName, SemVersion version) - { - using (var scope = ScopeProvider.CreateScope(autoComplete: true)) - { - return _migrationEntryRepository.FindEntry(migrationName, version); - } - } - - /// - /// Gets all entries for a given migration name - /// - /// - /// - public IEnumerable GetAll(string migrationName) - { - using (var scope = ScopeProvider.CreateScope(autoComplete: true)) - { - var query = Query() - .Where(x => x.MigrationName.ToUpper() == migrationName.ToUpper()); - return _migrationEntryRepository.Get(query); - } - } - - } -} diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index 80fbe6c71a..c8bdc7b2fd 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -7,7 +7,6 @@ namespace Umbraco.Core.Services /// public class ServiceContext { - private readonly Lazy _migrationEntryService; private readonly Lazy _publicAccessService; private readonly Lazy _taskService; private readonly Lazy _domainService; @@ -40,9 +39,8 @@ namespace Umbraco.Core.Services /// Initializes a new instance of the class with lazy services. /// /// Used by IoC. Note that LightInject will favor lazy args when picking a constructor. - public ServiceContext(Lazy migrationEntryService, Lazy publicAccessService, Lazy taskService, Lazy domainService, Lazy auditService, Lazy localizedTextService, Lazy tagService, Lazy contentService, Lazy userService, Lazy memberService, Lazy mediaService, Lazy contentTypeService, Lazy mediaTypeService, Lazy dataTypeService, Lazy fileService, Lazy localizationService, Lazy packagingService, Lazy serverRegistrationService, Lazy entityService, Lazy relationService, Lazy treeService, Lazy sectionService, Lazy macroService, Lazy memberTypeService, Lazy memberGroupService, Lazy notificationService, Lazy externalLoginService, Lazy redirectUrlService) + public ServiceContext(Lazy publicAccessService, Lazy taskService, Lazy domainService, Lazy auditService, Lazy localizedTextService, Lazy tagService, Lazy contentService, Lazy userService, Lazy memberService, Lazy mediaService, Lazy contentTypeService, Lazy mediaTypeService, Lazy dataTypeService, Lazy fileService, Lazy localizationService, Lazy packagingService, Lazy serverRegistrationService, Lazy entityService, Lazy relationService, Lazy treeService, Lazy sectionService, Lazy macroService, Lazy memberTypeService, Lazy memberGroupService, Lazy notificationService, Lazy externalLoginService, Lazy redirectUrlService) { - _migrationEntryService = migrationEntryService; _publicAccessService = publicAccessService; _taskService = taskService; _domainService = domainService; @@ -102,12 +100,10 @@ namespace Umbraco.Core.Services IMacroService macroService = null, IPublicAccessService publicAccessService = null, IExternalLoginService externalLoginService = null, - IMigrationEntryService migrationEntryService = null, IServerRegistrationService serverRegistrationService = null, IRedirectUrlService redirectUrlService = null) { if (serverRegistrationService != null) _serverRegistrationService = new Lazy(() => serverRegistrationService); - if (migrationEntryService != null) _migrationEntryService = new Lazy(() => migrationEntryService); if (externalLoginService != null) _externalLoginService = new Lazy(() => externalLoginService); if (auditService != null) _auditService = new Lazy(() => auditService); if (localizedTextService != null) _localizedTextService = new Lazy(() => localizedTextService); @@ -135,12 +131,7 @@ namespace Umbraco.Core.Services if (publicAccessService != null) _publicAccessService = new Lazy(() => publicAccessService); if (redirectUrlService != null) _redirectUrlService = new Lazy(() => redirectUrlService); } - - /// - /// Gets the - /// - public IMigrationEntryService MigrationEntryService => _migrationEntryService.Value; - + /// /// Gets the /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 89dd584850..20f5d50236 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -525,7 +525,7 @@ - + @@ -1336,7 +1336,6 @@ - @@ -1360,7 +1359,6 @@ - diff --git a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs index 0f76d11f3f..2566025e95 100644 --- a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs @@ -34,8 +34,8 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, - new MigrationPlan("test", ScopeProvider, builder, logger) + var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", builder, logger) .Add(string.Empty, "done")); upgrader.Execute(); @@ -71,8 +71,8 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, - new MigrationPlan("test", ScopeProvider, builder, logger) + var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", builder, logger) .Add(string.Empty, "a") .Add("a", "done")); @@ -106,8 +106,8 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, - new MigrationPlan("test", ScopeProvider, builder, logger) + var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", builder, logger) .Add(string.Empty, "a") .Add("a", "b") .Add("b", "done")); @@ -142,8 +142,8 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, - new MigrationPlan("test", ScopeProvider, builder, logger) + var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", builder, logger) .Add(string.Empty, "a") .Add("a", "b") .Add("b", "done")); @@ -176,8 +176,8 @@ namespace Umbraco.Tests.Migrations using (var scope = ScopeProvider.CreateScope()) { - var upgrader = new MigrationTests.TestUpgrader("test", ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, - new MigrationPlan("test", ScopeProvider, builder, logger) + var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of(), new PostMigrationCollection(Enumerable.Empty()), logger, + new MigrationPlan("test", builder, logger) .Add(string.Empty, "a") .Add("a", "done")); diff --git a/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs b/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs index 328d300cab..746330325e 100644 --- a/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs +++ b/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Migrations case "DeleteRedirectUrlTable": return new DeleteRedirectUrlTable(c); case "NopMigration": - return new NopMigration(); + return new NoopMigration(); default: throw new NotSupportedException(); } @@ -49,10 +49,10 @@ namespace Umbraco.Tests.Migrations // 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) + var plan = new MigrationPlan("default", migrationBuilder, logger) .From(string.Empty) .Chain("{4A9A1A8F-0DA1-4BCF-AD06-C19D79152E35}") - .Chain("VERSION.33"); + .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); @@ -81,7 +81,7 @@ namespace Umbraco.Tests.Migrations [Test] public void CanAddMigrations() { - var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + var plan = new MigrationPlan("default", Mock.Of(), Mock.Of()); plan.Add(string.Empty, "aaa"); plan.Add("aaa", "bbb"); plan.Add("bbb", "ccc"); @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Migrations [Test] public void CannotTransitionToSameState() { - var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + var plan = new MigrationPlan("default", Mock.Of(), Mock.Of()); Assert.Throws(() => { plan.Add("aaa", "aaa"); @@ -100,7 +100,7 @@ namespace Umbraco.Tests.Migrations [Test] public void OnlyOneTransitionPerState() { - var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + var plan = new MigrationPlan("default", Mock.Of(), Mock.Of()); plan.Add("aaa", "bbb"); Assert.Throws(() => { @@ -111,29 +111,31 @@ namespace Umbraco.Tests.Migrations [Test] public void CannotContainTwoMoreHeads() { - var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + var plan = new MigrationPlan("default", Mock.Of(), Mock.Of()); plan.Add(string.Empty, "aaa"); plan.Add("aaa", "bbb"); plan.Add("ccc", "ddd"); - Assert.Throws(plan.Validate); + Assert.Throws(() => plan.Validate()); } [Test] public void CannotContainLoops() { - var plan = new MigrationPlan("default", Mock.Of(), Mock.Of(), Mock.Of()); + var plan = new MigrationPlan("default", 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); + Assert.Throws(() => plan.Validate()); } [Test] public void ValidateUmbracoPlan() { - var plan = new UmbracoPlan(Mock.Of(), Mock.Of(), Mock.Of()); - plan.Validate(); + var plan = new UmbracoPlan(Mock.Of(), Mock.Of()); + var finalState = plan.Validate(); + Console.WriteLine(finalState); + Assert.IsFalse(string.IsNullOrWhiteSpace(finalState)); } public class DeleteRedirectUrlTable : MigrationBase diff --git a/src/Umbraco.Tests/Migrations/MigrationTests.cs b/src/Umbraco.Tests/Migrations/MigrationTests.cs index 67863e9494..0b1a19c31a 100644 --- a/src/Umbraco.Tests/Migrations/MigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/MigrationTests.cs @@ -17,8 +17,8 @@ namespace Umbraco.Tests.Migrations { 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) + public TestUpgrader(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations, ILogger logger, MigrationPlan plan) + : base(scopeProvider, migrationBuilder, keyValueService, postMigrations, logger) { _plan = plan; } diff --git a/src/Umbraco.Tests/Migrations/PostMigrationTests.cs b/src/Umbraco.Tests/Migrations/PostMigrationTests.cs index 18fe4c36db..accdb61ab7 100644 --- a/src/Umbraco.Tests/Migrations/PostMigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/PostMigrationTests.cs @@ -1,14 +1,11 @@ using System; -using System.Data; using Moq; using NPoco; using NUnit.Framework; using Semver; using Umbraco.Core; -using Umbraco.Core.Events; 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; @@ -38,7 +35,7 @@ namespace Umbraco.Tests.Migrations switch (t.Name) { case "NopMigration": - return new NopMigration(); + return new NoopMigration(); default: throw new NotSupportedException(); } @@ -53,9 +50,9 @@ namespace Umbraco.Tests.Migrations var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext }; - var u1 = new MigrationTests.TestUpgrader("Test", scopeProvider, builder, Mock.Of(), posts, logger, - new MigrationPlan("Test", scopeProvider, builder, logger) - .Add(string.Empty, "done")); + var u1 = new MigrationTests.TestUpgrader(scopeProvider, builder, Mock.Of(), posts, logger, + new MigrationPlan("Test", builder, logger) + .Add(string.Empty, "done")); u1.Execute(); Assert.AreEqual(1, changed1.CountExecuted); @@ -82,7 +79,7 @@ namespace Umbraco.Tests.Migrations switch (t.Name) { case "NopMigration": - return new NopMigration(); + return new NoopMigration(); default: throw new NotSupportedException(); } @@ -97,17 +94,17 @@ namespace Umbraco.Tests.Migrations var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of()); var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext }; - var u1 = new MigrationTests.TestUpgrader("Test1", scopeProvider, builder, Mock.Of(), posts, logger, - new MigrationPlan("Test1", scopeProvider, builder, logger) - .Add(string.Empty, "done")); + var u1 = new MigrationTests.TestUpgrader(scopeProvider, builder, Mock.Of(), posts, logger, + new MigrationPlan("Test1", builder, logger) + .Add(string.Empty, "done")); u1.Execute(); Assert.AreEqual(1, changed1.CountExecuted); Assert.AreEqual(0, changed2.CountExecuted); - var u2 = new MigrationTests.TestUpgrader("Test2", scopeProvider, builder, Mock.Of(), posts, logger, - new MigrationPlan("Test2", scopeProvider, builder, logger) - .Add(string.Empty, "done")); + var u2 = new MigrationTests.TestUpgrader(scopeProvider, builder, Mock.Of(), posts, logger, + new MigrationPlan("Test2", builder, logger) + .Add(string.Empty, "done")); u2.Execute(); Assert.AreEqual(1, changed1.CountExecuted); diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 176ca3bcad..94935cd961 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -4,7 +4,6 @@ using System.Web.Hosting; using LightInject; using Moq; using NUnit.Framework; -using Semver; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Composing; @@ -108,7 +107,7 @@ namespace Umbraco.Tests.Runtimes // pretend we have the proper migration // else BootFailedException because our mock IUmbracoDatabaseFactory does not provide databases - protected override bool EnsureMigration(IUmbracoDatabaseFactory databaseFactory, SemVersion codeVersion) + protected override bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) { return true; } diff --git a/src/Umbraco.Web/Migrations/ClearCsrfCookiesAfterUpgrade.cs b/src/Umbraco.Web/Migrations/ClearCsrfCookiesAfterUpgrade.cs index efa788d4f4..75ba97097b 100644 --- a/src/Umbraco.Web/Migrations/ClearCsrfCookiesAfterUpgrade.cs +++ b/src/Umbraco.Web/Migrations/ClearCsrfCookiesAfterUpgrade.cs @@ -15,7 +15,7 @@ namespace Umbraco.Web.Migrations { public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (name != Constants.System.UmbracoUpgraderName) return; + if (name != Constants.System.UmbracoUpgradePlanName) return; if (HttpContext.Current == null) return; var http = new HttpContextWrapper(HttpContext.Current); diff --git a/src/Umbraco.Web/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs b/src/Umbraco.Web/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs index 2ce2f3334a..04007a9a46 100644 --- a/src/Umbraco.Web/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs +++ b/src/Umbraco.Web/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Migrations public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (name != Constants.System.UmbracoUpgraderName) return; + if (name != Constants.System.UmbracoUpgradePlanName) return; var target70 = new SemVersion(7 /*, 0, 0*/); diff --git a/src/Umbraco.Web/Migrations/EnsureListViewDataTypeIsCreated.cs b/src/Umbraco.Web/Migrations/EnsureListViewDataTypeIsCreated.cs index 67ea5b1542..255e696528 100644 --- a/src/Umbraco.Web/Migrations/EnsureListViewDataTypeIsCreated.cs +++ b/src/Umbraco.Web/Migrations/EnsureListViewDataTypeIsCreated.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.Migrations { public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (name != Constants.System.UmbracoUpgraderName) return; + if (name != Constants.System.UmbracoUpgradePlanName) return; var target720 = new SemVersion(7, 2, 0); diff --git a/src/Umbraco.Web/Migrations/OverwriteStylesheetFilesFromTempFiles.cs b/src/Umbraco.Web/Migrations/OverwriteStylesheetFilesFromTempFiles.cs index 63a97befe8..380636c876 100644 --- a/src/Umbraco.Web/Migrations/OverwriteStylesheetFilesFromTempFiles.cs +++ b/src/Umbraco.Web/Migrations/OverwriteStylesheetFilesFromTempFiles.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Migrations { public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (name != Constants.System.UmbracoUpgraderName) return; + if (name != Constants.System.UmbracoUpgradePlanName) return; var target73 = new SemVersion(7, 3, 0); diff --git a/src/Umbraco.Web/Migrations/RebuildXmlCachesAfterUpgrade.cs b/src/Umbraco.Web/Migrations/RebuildXmlCachesAfterUpgrade.cs index 92774325ee..2181eea367 100644 --- a/src/Umbraco.Web/Migrations/RebuildXmlCachesAfterUpgrade.cs +++ b/src/Umbraco.Web/Migrations/RebuildXmlCachesAfterUpgrade.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Migrations { public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger) { - if (name != Constants.System.UmbracoUpgraderName) return; + if (name != Constants.System.UmbracoUpgradePlanName) return; var v730 = new SemVersion(new Version(7, 3, 0));