Cleanup the Umbraco migration plan

This commit is contained in:
Stephan
2018-07-04 18:19:06 +02:00
parent 84e0d0571f
commit b086fd2f0b
3 changed files with 87 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ using System.Linq;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Scoping;
using Type = System.Type;
namespace Umbraco.Core.Migrations
{
@@ -31,6 +32,11 @@ namespace Umbraco.Core.Migrations
DefinePlan();
}
/// <summary>
/// Gets the transitions.
/// </summary>
public IReadOnlyDictionary<string, Transition> Transitions => _transitions;
/// <summary>
/// Defines the plan.
/// </summary>
@@ -238,8 +244,8 @@ namespace Umbraco.Core.Migrations
{
Validate();
if (migrationBuilder == null || logger == null)
throw new InvalidOperationException("Cannot execute a non-executable plan.");
if (migrationBuilder == null) throw new ArgumentNullException(nameof(migrationBuilder));
if (logger == null) throw new ArgumentNullException(nameof(logger));
logger.Info<MigrationPlan>("Starting '{MigrationName}'...", Name);
@@ -275,10 +281,47 @@ namespace Umbraco.Core.Migrations
return origState;
}
/// <summary>
/// Follows a path (for tests and debugging).
/// </summary>
/// <remarks>Does the same thing Execute does, but does not actually execute migrations.</remarks>
internal string FollowPath(string fromState, string toState = null)
{
toState = toState.NullOrWhiteSpaceAsNull();
Validate();
var origState = fromState ?? string.Empty;
if (!_transitions.TryGetValue(origState, out var transition))
throw new Exception($"Unknown state \"{origState}\".");
while (transition != null)
{
var nextState = transition.TargetState;
origState = nextState;
if (nextState == toState)
{
transition = null;
continue;
}
if (!_transitions.TryGetValue(origState, out transition))
throw new Exception($"Unknown state \"{origState}\".");
}
// safety check
if (origState != (toState ?? _finalState))
throw new Exception($"Internal error, reached state {origState} which is not state {toState ?? _finalState}");
return origState;
}
/// <summary>
/// Represents a plan transition.
/// </summary>
private class Transition
public class Transition
{
/// <summary>
/// Initializes a new instance of the <see cref="Transition"/> class.

View File

@@ -41,6 +41,11 @@ namespace Umbraco.Core.Migrations.Upgrade
/// <param name="logger">A logger.</param>
public void Execute(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, ILogger logger)
{
if (scopeProvider == null) throw new ArgumentNullException(nameof(scopeProvider));
if (migrationBuilder == null) throw new ArgumentNullException(nameof(migrationBuilder));
if (keyValueService == null) throw new ArgumentNullException(nameof(keyValueService));
if (logger == null) throw new ArgumentNullException(nameof(logger));
var plan = Plan;
using (var scope = scopeProvider.CreateScope())

View File

@@ -1,7 +1,9 @@
using System;
using System.Linq;
using Moq;
using NPoco;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Migrations;
using Umbraco.Core.Migrations.Upgrade;
@@ -141,6 +143,40 @@ namespace Umbraco.Tests.Migrations
Assert.IsFalse(string.IsNullOrWhiteSpace(plan.FinalState));
}
[Test]
public void CanCopyChain()
{
var plan = new MigrationPlan("default");
plan
.From(string.Empty)
.To("aaa")
.To("bbb")
.To("ccc")
.To("ddd")
.To("eee");
plan
.From("xxx")
.To("yyy", "bbb", "ddd")
.To("eee");
WritePlanToConsole(plan);
plan.Validate();
Assert.AreEqual("eee", plan.FollowPath("xxx"));
Assert.AreEqual("yyy", plan.FollowPath("xxx", "yyy"));
}
private void WritePlanToConsole(MigrationPlan plan)
{
var final = plan.Transitions.First(x => x.Value == null).Key;
Console.WriteLine("plan \"{0}\" to final state \"{1}\":", plan.Name, final);
foreach (var (_, transition) in plan.Transitions)
if (transition != null)
Console.WriteLine(transition);
}
public class DeleteRedirectUrlTable : MigrationBase
{
public DeleteRedirectUrlTable(IMigrationContext context)