Merge branch temp8 into temp8-3675-variant-tags
This commit is contained in:
@@ -42,6 +42,17 @@ namespace Umbraco.Core.Composing
|
||||
private static LocalTempStorage _localTempStorage = LocalTempStorage.Unknown;
|
||||
private static string _fileBasePath;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypeLoader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="runtimeCache">The application runtime cache.</param>
|
||||
/// <param name="globalSettings"></param>
|
||||
/// <param name="logger">A profiling logger.</param>
|
||||
/// <remarks>Used by LightInject.</remarks>
|
||||
public TypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, ProfilingLogger logger)
|
||||
: this(runtimeCache, globalSettings, logger, true)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypeLoader"/> class.
|
||||
/// </summary>
|
||||
@@ -49,7 +60,7 @@ namespace Umbraco.Core.Composing
|
||||
/// <param name="globalSettings"></param>
|
||||
/// <param name="logger">A profiling logger.</param>
|
||||
/// <param name="detectChanges">Whether to detect changes using hashes.</param>
|
||||
internal TypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, ProfilingLogger logger, bool detectChanges = true)
|
||||
internal TypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, ProfilingLogger logger, bool detectChanges)
|
||||
{
|
||||
_runtimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache));
|
||||
_globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings));
|
||||
@@ -401,39 +412,6 @@ namespace Umbraco.Core.Composing
|
||||
return _fileBasePath;
|
||||
}
|
||||
|
||||
//private string GetFilePath(string extension)
|
||||
//{
|
||||
// string path;
|
||||
// switch (_globalSettings.LocalTempStorageLocation)
|
||||
// {
|
||||
// case LocalTempStorage.AspNetTemp:
|
||||
// path = Path.Combine(HttpRuntime.CodegenDir, "UmbracoData", "umbraco-types." + extension);
|
||||
// break;
|
||||
// case LocalTempStorage.EnvironmentTemp:
|
||||
// // include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// // to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// // utilizing an old path - assuming we cannot have SHA1 collisions on AppDomainAppId
|
||||
// var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
|
||||
// var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", appDomainHash);
|
||||
// path = Path.Combine(cachePath, "umbraco-types." + extension);
|
||||
// break;
|
||||
// case LocalTempStorage.Default:
|
||||
// default:
|
||||
// var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/TypesCache");
|
||||
// path = Path.Combine(tempFolder, "umbraco-types." + NetworkHelper.FileSafeMachineName + "." + extension);
|
||||
// break;
|
||||
// }
|
||||
|
||||
// // ensure that the folder exists
|
||||
// var directory = Path.GetDirectoryName(path);
|
||||
// if (directory == null)
|
||||
// throw new InvalidOperationException($"Could not determine folder for file \"{path}\".");
|
||||
// if (Directory.Exists(directory) == false)
|
||||
// Directory.CreateDirectory(directory);
|
||||
|
||||
// return path;
|
||||
//}
|
||||
|
||||
// internal for tests
|
||||
internal void WriteCache()
|
||||
{
|
||||
|
||||
@@ -202,7 +202,6 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
private static bool IsTimeoutThreadAbortException(Exception exception)
|
||||
{
|
||||
if (!(exception is ThreadAbortException abort)) return false;
|
||||
|
||||
if (abort.ExceptionState == null) return false;
|
||||
|
||||
var stateType = abort.ExceptionState.GetType();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using NPoco;
|
||||
using Umbraco.Core.Migrations.Expressions.Common;
|
||||
using Umbraco.Core.Migrations.Expressions.Execute.Expressions;
|
||||
using Umbraco.Core.Persistence;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Expressions.Execute
|
||||
{
|
||||
@@ -12,7 +13,16 @@ namespace Umbraco.Core.Migrations.Expressions.Execute
|
||||
{ }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Do() => Expression.Execute();
|
||||
public void Do()
|
||||
{
|
||||
// slightly awkward, but doing it right would mean a *lot*
|
||||
// of changes for MigrationExpressionBase
|
||||
|
||||
if (Expression.SqlObject == null)
|
||||
Expression.Execute();
|
||||
else
|
||||
Expression.ExecuteSqlObject();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IExecutableBuilder Sql(string sqlStatement)
|
||||
@@ -20,5 +30,12 @@ namespace Umbraco.Core.Migrations.Expressions.Execute
|
||||
Expression.SqlStatement = sqlStatement;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IExecutableBuilder Sql(Sql<ISqlContext> sql)
|
||||
{
|
||||
Expression.SqlObject = sql;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using NPoco;
|
||||
using Umbraco.Core.Persistence;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Expressions.Execute.Expressions
|
||||
{
|
||||
@@ -10,6 +11,13 @@ namespace Umbraco.Core.Migrations.Expressions.Execute.Expressions
|
||||
|
||||
public virtual string SqlStatement { get; set; }
|
||||
|
||||
public virtual Sql<ISqlContext> SqlObject { get; set; }
|
||||
|
||||
public void ExecuteSqlObject()
|
||||
{
|
||||
Execute(SqlObject);
|
||||
}
|
||||
|
||||
protected override string GetSql()
|
||||
{
|
||||
return SqlStatement;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Umbraco.Core.Migrations.Expressions.Common;
|
||||
using NPoco;
|
||||
using Umbraco.Core.Migrations.Expressions.Common;
|
||||
using Umbraco.Core.Persistence;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Expressions.Execute
|
||||
{
|
||||
@@ -12,5 +14,10 @@ namespace Umbraco.Core.Migrations.Expressions.Execute
|
||||
/// Specifies the Sql statement to execute.
|
||||
/// </summary>
|
||||
IExecutableBuilder Sql(string sqlStatement);
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the Sql statement to execute.
|
||||
/// </summary>
|
||||
IExecutableBuilder Sql(Sql<ISqlContext> sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,56 +534,11 @@ namespace Umbraco.Core.Migrations.Install
|
||||
|
||||
_logger.Info<DatabaseBuilder>("Database upgrade started");
|
||||
|
||||
//var database = scope.Database;
|
||||
//var supportsCaseInsensitiveQueries = SqlSyntax.SupportsCaseInsensitiveQueries(database);
|
||||
|
||||
var message = GetResultMessageForMySql();
|
||||
|
||||
// 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());
|
||||
//}
|
||||
|
||||
// upgrade
|
||||
var upgrader = new UmbracoUpgrader(_scopeProvider, _migrationBuilder, _keyValueService, _postMigrations, _logger);
|
||||
upgrader.Execute();
|
||||
|
||||
// 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");
|
||||
//}
|
||||
var upgrader = new UmbracoUpgrader();
|
||||
upgrader.Execute(_scopeProvider, _migrationBuilder, _keyValueService, _logger, _postMigrations);
|
||||
|
||||
message = message + "<p>Upgrade completed!</p>";
|
||||
|
||||
|
||||
@@ -321,9 +321,9 @@ namespace Umbraco.Core.Migrations.Install
|
||||
{
|
||||
// on install, initialize the umbraco migration plan with the final state
|
||||
|
||||
var plan = new UmbracoPlan();
|
||||
var stateValueKey = Upgrader.GetStateValueKey(plan);
|
||||
var finalState = plan.FinalState;
|
||||
var upgrader = new UmbracoUpgrader();
|
||||
var stateValueKey = upgrader.StateValueKey;
|
||||
var finalState = upgrader.Plan.FinalState;
|
||||
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.KeyValue, "key", false, new KeyValueDto { Key = stateValueKey, Value = finalState, Updated = DateTime.Now });
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NPoco;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -88,6 +87,31 @@ namespace Umbraco.Core.Migrations
|
||||
expression.Execute();
|
||||
}
|
||||
|
||||
protected void Execute(Sql<ISqlContext> sql)
|
||||
{
|
||||
if (_executed)
|
||||
throw new InvalidOperationException("This expression has already been executed.");
|
||||
_executed = true;
|
||||
|
||||
if (sql == null)
|
||||
{
|
||||
Logger.Info(GetType(), $"SQL [{Context.Index}]: <empty>");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info(GetType(), $"SQL [{Context.Index}]: {sql.ToText()}");
|
||||
Database.Execute(sql);
|
||||
}
|
||||
|
||||
Context.Index++;
|
||||
|
||||
if (_expressions == null)
|
||||
return;
|
||||
|
||||
foreach (var expression in _expressions)
|
||||
expression.Execute();
|
||||
}
|
||||
|
||||
private void ExecuteStatement(StringBuilder stmtBuilder)
|
||||
{
|
||||
var stmt = stmtBuilder.ToString();
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -12,8 +13,6 @@ namespace Umbraco.Core.Migrations
|
||||
/// </summary>
|
||||
public class MigrationPlan
|
||||
{
|
||||
private readonly IMigrationBuilder _migrationBuilder;
|
||||
private readonly ILogger _logger;
|
||||
private readonly Dictionary<string, Transition> _transitions = new Dictionary<string, Transition>();
|
||||
|
||||
private string _prevState;
|
||||
@@ -23,64 +22,24 @@ namespace Umbraco.Core.Migrations
|
||||
/// Initializes a new instance of the <see cref="MigrationPlan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the plan.</param>
|
||||
/// <remarks>The plan cannot be executed. Use this constructor e.g. when only validating the plan,
|
||||
/// or trying to get its final state, without actually needing to execute it.</remarks>
|
||||
public MigrationPlan(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
|
||||
Name = name;
|
||||
|
||||
// ReSharper disable once VirtualMemberCallInConstructor
|
||||
// (accepted)
|
||||
DefinePlan();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MigrationPlan"/> class.
|
||||
/// Gets the transitions.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the plan.</param>
|
||||
/// <param name="migrationBuilder">A migration builder.</param>
|
||||
/// <param name="logger">A logger.</param>
|
||||
/// <remarks>The plan can be executed.</remarks>
|
||||
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));
|
||||
|
||||
// ReSharper disable once VirtualMemberCallInConstructor
|
||||
// (accepted)
|
||||
DefinePlan();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the plan.
|
||||
/// </summary>
|
||||
protected virtual void DefinePlan() { }
|
||||
public IReadOnlyDictionary<string, Transition> Transitions => _transitions;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the plan.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds an empty migration from source to target state.
|
||||
/// </summary>
|
||||
public MigrationPlan Add(string sourceState, string targetState)
|
||||
=> Add<NoopMigration>(sourceState, targetState);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a migration from source to target state.
|
||||
/// </summary>
|
||||
public MigrationPlan Add<TMigration>(string sourceState, string targetState)
|
||||
where TMigration : IMigration
|
||||
=> Add(sourceState, targetState, typeof(TMigration));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a migration from source to target state.
|
||||
/// </summary>
|
||||
public MigrationPlan Add(string sourceState, string targetState, Type migration)
|
||||
// adds a transition
|
||||
private 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));
|
||||
@@ -113,26 +72,26 @@ namespace Umbraco.Core.Migrations
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Chains an empty migration from chain to target state.
|
||||
/// </summary>
|
||||
public MigrationPlan Chain(string targetState)
|
||||
=> Chain<NoopMigration>(targetState);
|
||||
/// Adds a transition to a target state through an empty migration.
|
||||
/// </summary>
|
||||
public MigrationPlan To(string targetState)
|
||||
=> To<NoopMigration>(targetState);
|
||||
|
||||
/// <summary>
|
||||
/// Chains a migration from chain to target state.
|
||||
/// Adds a transition to a target state through a migration.
|
||||
/// </summary>
|
||||
public MigrationPlan Chain<TMigration>(string targetState)
|
||||
public MigrationPlan To<TMigration>(string targetState)
|
||||
where TMigration : IMigration
|
||||
=> Chain(targetState, typeof(TMigration));
|
||||
=> To(targetState, typeof(TMigration));
|
||||
|
||||
/// <summary>
|
||||
/// Chains a migration from chain to target state.
|
||||
/// Adds a transition to a target state through a migration.
|
||||
/// </summary>
|
||||
public MigrationPlan Chain(string targetState, Type migration)
|
||||
public MigrationPlan To(string targetState, Type migration)
|
||||
=> Add(_prevState, targetState, migration);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the chain state.
|
||||
/// Sets the starting state.
|
||||
/// </summary>
|
||||
public MigrationPlan From(string sourceState)
|
||||
{
|
||||
@@ -141,19 +100,16 @@ namespace Umbraco.Core.Migrations
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies a chain.
|
||||
/// Adds transitions to a target state by copying transitions from a start state to an end state.
|
||||
/// </summary>
|
||||
/// <remarks>Copies the chain going from startState to endState, with new states going from sourceState to targetState.</remarks>
|
||||
public MigrationPlan CopyChain(string sourceState, string startState, string endState, string targetState)
|
||||
public MigrationPlan To(string targetState, string startState, string endState)
|
||||
{
|
||||
if (sourceState == null) throw new ArgumentNullException(nameof(sourceState));
|
||||
if (string.IsNullOrWhiteSpace(startState)) throw new ArgumentNullOrEmptyException(nameof(startState));
|
||||
if (string.IsNullOrWhiteSpace(endState)) throw new ArgumentNullOrEmptyException(nameof(endState));
|
||||
if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentNullOrEmptyException(nameof(targetState));
|
||||
if (sourceState == targetState) throw new ArgumentException("Source and target states cannot be identical.");
|
||||
|
||||
if (startState == endState) throw new ArgumentException("Start and end states cannot be identical.");
|
||||
|
||||
sourceState = sourceState.Trim();
|
||||
startState = startState.Trim();
|
||||
endState = endState.Trim();
|
||||
targetState = targetState.Trim();
|
||||
@@ -168,26 +124,18 @@ namespace Umbraco.Core.Migrations
|
||||
visited.Add(state);
|
||||
|
||||
if (!_transitions.TryGetValue(state, out var transition))
|
||||
throw new InvalidOperationException($"There is no transition from state \"{sourceState}\".");
|
||||
throw new InvalidOperationException($"There is no transition from state \"{state}\".");
|
||||
|
||||
var newTargetState = transition.TargetState == endState
|
||||
? targetState
|
||||
: Guid.NewGuid().ToString("B").ToUpper();
|
||||
Add(sourceState, newTargetState, transition.MigrationType);
|
||||
sourceState = newTargetState;
|
||||
To(newTargetState, transition.MigrationType);
|
||||
state = transition.TargetState;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies a chain.
|
||||
/// </summary>
|
||||
/// <remarks>Copies the chain going from startState to endState, with new states going from chain to targetState.</remarks>
|
||||
public MigrationPlan CopyChain(string startState, string endState, string targetState)
|
||||
=> CopyChain(_prevState, startState, endState, targetState);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the initial state.
|
||||
/// </summary>
|
||||
@@ -260,50 +208,92 @@ namespace Umbraco.Core.Migrations
|
||||
/// </summary>
|
||||
/// <param name="scope">A scope.</param>
|
||||
/// <param name="fromState">The state to start execution at.</param>
|
||||
/// <param name="migrationBuilder">A migration builder.</param>
|
||||
/// <param name="logger">A logger.</param>
|
||||
/// <returns>The final state.</returns>
|
||||
/// <remarks>The plan executes within the scope, which must then be completed.</remarks>
|
||||
public string Execute(IScope scope, string fromState)
|
||||
public string Execute(IScope scope, string fromState, IMigrationBuilder migrationBuilder, ILogger logger)
|
||||
{
|
||||
Validate();
|
||||
|
||||
if (_migrationBuilder == null || _logger == null)
|
||||
throw new InvalidOperationException("Cannot execute a non-executing plan.");
|
||||
if (migrationBuilder == null) throw new ArgumentNullException(nameof(migrationBuilder));
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
_logger.Info<MigrationPlan>("Starting '{MigrationName}'...", Name);
|
||||
logger.Info<MigrationPlan>("Starting '{MigrationName}'...", Name);
|
||||
|
||||
var origState = fromState ?? string.Empty;
|
||||
|
||||
_logger.Info<MigrationPlan>("At {OrigState}", string.IsNullOrWhiteSpace(origState) ? "origin": origState);
|
||||
logger.Info<MigrationPlan>("At {OrigState}", string.IsNullOrWhiteSpace(origState) ? "origin": origState);
|
||||
|
||||
if (!_transitions.TryGetValue(origState, out var transition))
|
||||
throw new Exception($"Unknown state \"{origState}\".");
|
||||
|
||||
var context = new MigrationContext(scope.Database, _logger);
|
||||
var context = new MigrationContext(scope.Database, logger);
|
||||
|
||||
while (transition != null)
|
||||
{
|
||||
var migration = _migrationBuilder.Build(transition.MigrationType, context);
|
||||
var migration = migrationBuilder.Build(transition.MigrationType, context);
|
||||
migration.Migrate();
|
||||
|
||||
var nextState = transition.TargetState;
|
||||
origState = nextState;
|
||||
|
||||
_logger.Info<MigrationPlan>("At {OrigState}", origState);
|
||||
logger.Info<MigrationPlan>("At {OrigState}", origState);
|
||||
|
||||
if (!_transitions.TryGetValue(origState, out transition))
|
||||
throw new Exception($"Unknown state \"{origState}\".");
|
||||
}
|
||||
|
||||
_logger.Info<MigrationPlan>("Done (pending scope completion).");
|
||||
logger.Info<MigrationPlan>("Done (pending scope completion).");
|
||||
|
||||
// safety check
|
||||
if (origState != _finalState)
|
||||
throw new Exception($"Internal error, reached state {origState} which is not final state {_finalState}");
|
||||
|
||||
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}");
|
||||
|
||||
// fixme - what about post-migrations?
|
||||
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.
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Configuration;
|
||||
using Semver;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_7_12_0;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
@@ -18,14 +17,9 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
/// </summary>
|
||||
public UmbracoPlan()
|
||||
: base(Constants.System.UmbracoUpgradePlanName)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoPlan"/> class.
|
||||
/// </summary>
|
||||
public UmbracoPlan(IMigrationBuilder migrationBuilder, ILogger logger)
|
||||
: base(Constants.System.UmbracoUpgradePlanName, migrationBuilder, logger)
|
||||
{ }
|
||||
{
|
||||
DefinePlan();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <remarks>
|
||||
@@ -61,8 +55,8 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void DefinePlan()
|
||||
// define the plan
|
||||
protected void DefinePlan()
|
||||
{
|
||||
// MODIFYING THE PLAN
|
||||
//
|
||||
@@ -85,66 +79,74 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
// upgrades from 7 to 8, and then takes care of all eventual upgrades
|
||||
//
|
||||
From("{init-7.10.0}");
|
||||
Chain<AddLockObjects>("{7C447271-CA3F-4A6A-A913-5D77015655CB}");
|
||||
Chain<AddContentNuTable>("{CBFF58A2-7B50-4F75-8E98-249920DB0F37}");
|
||||
Chain<RefactorXmlColumns>("{3D18920C-E84D-405C-A06A-B7CEE52FE5DD}");
|
||||
Chain<VariantsMigration>("{FB0A5429-587E-4BD0-8A67-20F0E7E62FF7}");
|
||||
Chain<DropMigrationsTable>("{F0C42457-6A3B-4912-A7EA-F27ED85A2092}");
|
||||
Chain<DataTypeMigration>("{8640C9E4-A1C0-4C59-99BB-609B4E604981}");
|
||||
Chain<TagsMigration>("{DD1B99AF-8106-4E00-BAC7-A43003EA07F8}");
|
||||
Chain<SuperZero>("{9DF05B77-11D1-475C-A00A-B656AF7E0908}");
|
||||
Chain<PropertyEditorsMigration>("{6FE3EF34-44A0-4992-B379-B40BC4EF1C4D}");
|
||||
Chain<LanguageColumns>("{7F59355A-0EC9-4438-8157-EB517E6D2727}");
|
||||
To<AddLockObjects>("{7C447271-CA3F-4A6A-A913-5D77015655CB}");
|
||||
To<AddContentNuTable>("{CBFF58A2-7B50-4F75-8E98-249920DB0F37}");
|
||||
To<RefactorXmlColumns>("{3D18920C-E84D-405C-A06A-B7CEE52FE5DD}");
|
||||
To<VariantsMigration>("{FB0A5429-587E-4BD0-8A67-20F0E7E62FF7}");
|
||||
To<DropMigrationsTable>("{F0C42457-6A3B-4912-A7EA-F27ED85A2092}");
|
||||
To<DataTypeMigration>("{8640C9E4-A1C0-4C59-99BB-609B4E604981}");
|
||||
To<TagsMigration>("{DD1B99AF-8106-4E00-BAC7-A43003EA07F8}");
|
||||
To<SuperZero>("{9DF05B77-11D1-475C-A00A-B656AF7E0908}");
|
||||
To<PropertyEditorsMigration>("{6FE3EF34-44A0-4992-B379-B40BC4EF1C4D}");
|
||||
To<LanguageColumns>("{7F59355A-0EC9-4438-8157-EB517E6D2727}");
|
||||
//To<AddVariationTables1>("{941B2ABA-2D06-4E04-81F5-74224F1DB037}"); // AddVariationTables1 has been superseded by AddVariationTables2
|
||||
To<AddVariationTables2>("{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}");
|
||||
|
||||
// AddVariationTables1 has been superceeded by AddVariationTables2
|
||||
//Chain<AddVariationTables1>("{941B2ABA-2D06-4E04-81F5-74224F1DB037}");
|
||||
Chain<AddVariationTables2>("{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}");
|
||||
// however, provide a path out of the old state
|
||||
Add<AddVariationTables1A>("{941B2ABA-2D06-4E04-81F5-74224F1DB037}", "{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}");
|
||||
// way out of the commented state
|
||||
From("{941B2ABA-2D06-4E04-81F5-74224F1DB037}");
|
||||
To<AddVariationTables1A>("{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}");
|
||||
// resume at {76DF5CD7-A884-41A5-8DC6-7860D95B1DF5} ...
|
||||
|
||||
Chain<RefactorMacroColumns>("{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
|
||||
To<RefactorMacroColumns>("{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
|
||||
To<UserForeignKeys>("{3E44F712-E2E3-473A-AE49-5D7F8E67CE3F}"); // shannon added that one - let's keep it as the default path
|
||||
//To<AddTypedLabels>("{65D6B71C-BDD5-4A2E-8D35-8896325E9151}"); // stephan added that one = merge conflict, remove
|
||||
To<AddTypedLabels>("{4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4}"); // but add it after shannon's, with a new target state
|
||||
|
||||
Chain<UserForeignKeys>("{3E44F712-E2E3-473A-AE49-5D7F8E67CE3F}"); // shannon added that one - let's keep it as the default path
|
||||
//Chain<AddTypedLabels>("{65D6B71C-BDD5-4A2E-8D35-8896325E9151}"); // stephan added that one = merge conflict, remove,
|
||||
Chain<AddTypedLabels>("{4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4}"); // but add it after shannon's, with a new target state,
|
||||
Add<UserForeignKeys>("{65D6B71C-BDD5-4A2E-8D35-8896325E9151}", "{4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4}"); // and provide a path out of the conflict state
|
||||
// way out of the commented state
|
||||
From("{65D6B71C-BDD5-4A2E-8D35-8896325E9151}");
|
||||
To<UserForeignKeys>("{4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4}");
|
||||
// resume at {4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4} ...
|
||||
|
||||
Chain<ContentVariationMigration>("{1350617A-4930-4D61-852F-E3AA9E692173}");
|
||||
Chain<UpdateUmbracoConsent>("{39E5B1F7-A50B-437E-B768-1723AEC45B65}"); // from 7.12.0
|
||||
//Chain<FallbackLanguage>("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}"); // andy added that one = merge conflict, remove
|
||||
Chain<AddRelationTypeForMediaFolderOnDelete>("{0541A62B-EF87-4CA2-8225-F0EB98ECCC9F}"); // from 7.12.0
|
||||
Chain<IncreaseLanguageIsoCodeColumnLength>("{EB34B5DC-BB87-4005-985E-D983EA496C38}"); // from 7.12.0
|
||||
Chain<RenameTrueFalseField>("{517CE9EA-36D7-472A-BF4B-A0D6FB1B8F89}"); // from 7.12.0
|
||||
Chain<SetDefaultTagsStorageType>("{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}"); // from 7.12.0
|
||||
//Chain<UpdateDefaultMandatoryLanguage>("{2C87AA47-D1BC-4ECB-8A73-2D8D1046C27F}"); // stephan added that one = merge conflict, remove
|
||||
To<ContentVariationMigration>("{1350617A-4930-4D61-852F-E3AA9E692173}");
|
||||
To<UpdateUmbracoConsent>("{39E5B1F7-A50B-437E-B768-1723AEC45B65}"); // from 7.12.0
|
||||
//To<FallbackLanguage>("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}"); // andy added that one = merge conflict, remove
|
||||
To<AddRelationTypeForMediaFolderOnDelete>("{0541A62B-EF87-4CA2-8225-F0EB98ECCC9F}"); // from 7.12.0
|
||||
To<IncreaseLanguageIsoCodeColumnLength>("{EB34B5DC-BB87-4005-985E-D983EA496C38}"); // from 7.12.0
|
||||
To<RenameTrueFalseField>("{517CE9EA-36D7-472A-BF4B-A0D6FB1B8F89}"); // from 7.12.0
|
||||
To<SetDefaultTagsStorageType>("{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}"); // from 7.12.0
|
||||
//To<UpdateDefaultMandatoryLanguage>("{2C87AA47-D1BC-4ECB-8A73-2D8D1046C27F}"); // stephan added that one = merge conflict, remove
|
||||
|
||||
Chain<FallbackLanguage>("{8B14CEBD-EE47-4AAD-A841-93551D917F11}"); // add andy's after others, with a new target state
|
||||
From("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}") // and provide a path out of andy's
|
||||
.CopyChain("{39E5B1F7-A50B-437E-B768-1723AEC45B65}", "{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}", "{8B14CEBD-EE47-4AAD-A841-93551D917F11}"); // to next
|
||||
To<FallbackLanguage>("{8B14CEBD-EE47-4AAD-A841-93551D917F11}"); // add andy's after others, with a new target state
|
||||
|
||||
// way out of andy's
|
||||
From("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}");
|
||||
To("{8B14CEBD-EE47-4AAD-A841-93551D917F11}", "{39E5B1F7-A50B-437E-B768-1723AEC45B65}", "{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}");
|
||||
// resume at {8B14CEBD-EE47-4AAD-A841-93551D917F11} ...
|
||||
|
||||
Chain<UpdateDefaultMandatoryLanguage>("{5F4597F4-A4E0-4AFE-90B5-6D2F896830EB}"); // add stephan's after others, with a new target state
|
||||
From("{2C87AA47-D1BC-4ECB-8A73-2D8D1046C27F}") // and provide a path out of stephan's
|
||||
.Chain<FallbackLanguage>("{5F4597F4-A4E0-4AFE-90B5-6D2F896830EB}"); // to next
|
||||
To<UpdateDefaultMandatoryLanguage>("{5F4597F4-A4E0-4AFE-90B5-6D2F896830EB}"); // add stephan's after others, with a new target state
|
||||
|
||||
// way out of the commented state
|
||||
From("{2C87AA47-D1BC-4ECB-8A73-2D8D1046C27F}");
|
||||
To<FallbackLanguage>("{5F4597F4-A4E0-4AFE-90B5-6D2F896830EB}"); // to next
|
||||
// resume at {5F4597F4-A4E0-4AFE-90B5-6D2F896830EB} ...
|
||||
|
||||
//Chain<RefactorVariantsModel>("{B19BF0F2-E1C6-4AEB-A146-BC559D97A2C6}");
|
||||
Chain<RefactorVariantsModel>("{290C18EE-B3DE-4769-84F1-1F467F3F76DA}");
|
||||
From("{B19BF0F2-E1C6-4AEB-A146-BC559D97A2C6}")
|
||||
.Chain<FallbackLanguage>("{290C18EE-B3DE-4769-84F1-1F467F3F76DA}");
|
||||
//To<RefactorVariantsModel>("{B19BF0F2-E1C6-4AEB-A146-BC559D97A2C6}");
|
||||
To<RefactorVariantsModel>("{290C18EE-B3DE-4769-84F1-1F467F3F76DA}");
|
||||
|
||||
// way out of the commented state
|
||||
From("{B19BF0F2-E1C6-4AEB-A146-BC559D97A2C6}");
|
||||
To<FallbackLanguage>("{290C18EE-B3DE-4769-84F1-1F467F3F76DA}");
|
||||
// resume at {290C18EE-B3DE-4769-84F1-1F467F3F76DA}...
|
||||
|
||||
Chain<DropTaskTables>("{6A2C7C1B-A9DB-4EA9-B6AB-78E7D5B722A7}");
|
||||
Chain<FixLockTablePrimaryKey>("{77874C77-93E5-4488-A404-A630907CEEF0}");
|
||||
Chain<AddLogTableColumns>("{8804D8E8-FE62-4E3A-B8A2-C047C2118C38}");
|
||||
Chain<DropPreValueTable>("{23275462-446E-44C7-8C2C-3B8C1127B07D}");
|
||||
Chain<DropDownPropertyEditorsMigration>("{6B251841-3069-4AD5-8AE9-861F9523E8DA}");
|
||||
Chain<TagsMigrationFix>("{EE429F1B-9B26-43CA-89F8-A86017C809A3}");
|
||||
Chain<DropTemplateDesignColumn>("{08919C4B-B431-449C-90EC-2B8445B5C6B1}");
|
||||
Chain<TablesForScheduledPublishing>("{7EB0254C-CB8B-4C75-B15B-D48C55B449EB}");
|
||||
Chain<MakeTagsVariant>("{C39BF2A7-1454-4047-BBFE-89E40F66ED63}");
|
||||
To<DropTaskTables>("{6A2C7C1B-A9DB-4EA9-B6AB-78E7D5B722A7}");
|
||||
To<FixLockTablePrimaryKey>("{77874C77-93E5-4488-A404-A630907CEEF0}");
|
||||
To<AddLogTableColumns>("{8804D8E8-FE62-4E3A-B8A2-C047C2118C38}");
|
||||
To<DropPreValueTable>("{23275462-446E-44C7-8C2C-3B8C1127B07D}");
|
||||
To<DropDownPropertyEditorsMigration>("{6B251841-3069-4AD5-8AE9-861F9523E8DA}");
|
||||
To<TagsMigrationFix>("{EE429F1B-9B26-43CA-89F8-A86017C809A3}");
|
||||
To<DropTemplateDesignColumn>("{08919C4B-B431-449C-90EC-2B8445B5C6B1}");
|
||||
To<TablesForScheduledPublishing>("{7EB0254C-CB8B-4C75-B15B-D48C55B449EB}");
|
||||
To<MakeTagsVariant>("{C39BF2A7-1454-4047-BBFE-89E40F66ED63}");
|
||||
|
||||
//FINAL
|
||||
|
||||
@@ -153,20 +155,20 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
|
||||
// and then, need to support upgrading from more recent 7.x
|
||||
//
|
||||
From("{init-7.10.1}").Chain("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.2}").Chain("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.3}").Chain("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.4}").Chain("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.11.0}").Chain("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.11.1}").Chain("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.1}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.2}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.3}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.4}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.11.0}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.11.1}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
|
||||
// 7.12.0 has migrations, define a custom chain which copies the chain
|
||||
// going from {init-7.10.0} to former final (1350617A) , and then goes straight to
|
||||
// main chain, skipping the migrations
|
||||
//
|
||||
From("{init-7.12.0}");
|
||||
// copy from copy to (former final) main chain
|
||||
CopyChain("{init-7.10.0}", "{1350617A-4930-4D61-852F-E3AA9E692173}", "{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}");
|
||||
// target copy from copy to (former final)
|
||||
To("{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}", "{init-7.10.0}", "{1350617A-4930-4D61-852F-E3AA9E692173}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,24 +8,41 @@ using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Umbraco upgrader.
|
||||
/// </summary>
|
||||
public class UmbracoUpgrader : Upgrader
|
||||
{
|
||||
public UmbracoUpgrader(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations, ILogger logger)
|
||||
: base(scopeProvider, migrationBuilder, keyValueService, postMigrations, logger)
|
||||
private PostMigrationCollection _postMigrations;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see ref="UmbracoUpgrader" /> class.
|
||||
/// </summary>
|
||||
public UmbracoUpgrader()
|
||||
: base(new UmbracoPlan())
|
||||
{ }
|
||||
|
||||
protected override MigrationPlan GetPlan()
|
||||
/// <summary>
|
||||
/// Executes.
|
||||
/// </summary>
|
||||
public void Execute(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, ILogger logger, PostMigrationCollection postMigrations)
|
||||
{
|
||||
return new UmbracoPlan(MigrationBuilder, Logger);
|
||||
_postMigrations = postMigrations;
|
||||
Execute(scopeProvider, migrationBuilder, keyValueService, logger);
|
||||
}
|
||||
|
||||
protected override (SemVersion, SemVersion) GetVersions()
|
||||
/// <inheritdoc />
|
||||
public override void AfterMigrations(IScope scope, ILogger logger)
|
||||
{
|
||||
// assume we have something in web.config that makes some sense
|
||||
if (!SemVersion.TryParse(ConfigurationManager.AppSettings["umbracoConfigurationStatus"], out var currentVersion))
|
||||
// assume we have something in web.config that makes some sense = the origin version
|
||||
if (!SemVersion.TryParse(ConfigurationManager.AppSettings["umbracoConfigurationStatus"], out var originVersion))
|
||||
throw new InvalidOperationException("Could not get current version from web.config umbracoConfigurationStatus appSetting.");
|
||||
|
||||
return (currentVersion, UmbracoVersion.SemanticVersion);
|
||||
// target version is the code version
|
||||
var targetVersion = UmbracoVersion.SemanticVersion;
|
||||
|
||||
foreach (var postMigration in _postMigrations)
|
||||
postMigration.Execute(Name, scope, originVersion, targetVersion, logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,60 @@
|
||||
using System;
|
||||
using Semver;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade
|
||||
{
|
||||
public abstract class Upgrader
|
||||
/// <summary>
|
||||
/// Represents an upgrader.
|
||||
/// </summary>
|
||||
public class Upgrader
|
||||
{
|
||||
private readonly IKeyValueService _keyValueService;
|
||||
private readonly PostMigrationCollection _postMigrations;
|
||||
private MigrationPlan _plan;
|
||||
|
||||
protected Upgrader(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations, ILogger logger)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see ref="Upgrader"/> class.
|
||||
/// </summary>
|
||||
public Upgrader(MigrationPlan plan)
|
||||
{
|
||||
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));
|
||||
Plan = plan;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the migration plan.
|
||||
/// </summary>
|
||||
public string Name => Plan.Name;
|
||||
|
||||
public string StateValueKey => GetStateValueKey(Plan);
|
||||
/// <summary>
|
||||
/// Gets the migration plan.
|
||||
/// </summary>
|
||||
public MigrationPlan Plan { get; }
|
||||
|
||||
protected IScopeProvider ScopeProvider { get; }
|
||||
/// <summary>
|
||||
/// Gets the key for the state value.
|
||||
/// </summary>
|
||||
public virtual string StateValueKey => "Umbraco.Core.Upgrader.State+" + Name;
|
||||
|
||||
protected IMigrationBuilder MigrationBuilder { get; }
|
||||
|
||||
protected ILogger Logger { get; }
|
||||
|
||||
protected MigrationPlan Plan => _plan ?? (_plan = GetPlan());
|
||||
|
||||
protected abstract MigrationPlan GetPlan();
|
||||
protected abstract (SemVersion, SemVersion) GetVersions();
|
||||
|
||||
public void Execute()
|
||||
/// <summary>
|
||||
/// Executes.
|
||||
/// </summary>
|
||||
/// <param name="scopeProvider">A scope provider.</param>
|
||||
/// <param name="migrationBuilder">A migration builder.</param>
|
||||
/// <param name="keyValueService">A key-value service.</param>
|
||||
/// <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())
|
||||
using (var scope = scopeProvider.CreateScope())
|
||||
{
|
||||
BeforeMigrations(scope, logger);
|
||||
|
||||
// read current state
|
||||
var currentState = _keyValueService.GetValue(StateValueKey);
|
||||
var currentState = keyValueService.GetValue(StateValueKey);
|
||||
var forceState = false;
|
||||
|
||||
if (currentState == null)
|
||||
@@ -53,25 +64,33 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
}
|
||||
|
||||
// execute plan
|
||||
var state = plan.Execute(scope, currentState);
|
||||
var state = plan.Execute(scope, currentState, migrationBuilder, logger);
|
||||
if (string.IsNullOrWhiteSpace(state))
|
||||
throw new Exception("Plan execution returned an invalid null or empty state.");
|
||||
|
||||
// save new state
|
||||
if (forceState)
|
||||
_keyValueService.SetValue(StateValueKey, state);
|
||||
keyValueService.SetValue(StateValueKey, state);
|
||||
else if (currentState != state)
|
||||
_keyValueService.SetValue(StateValueKey, currentState, state);
|
||||
keyValueService.SetValue(StateValueKey, currentState, state);
|
||||
|
||||
// run post-migrations
|
||||
(var originVersion, var targetVersion) = GetVersions();
|
||||
foreach (var postMigration in _postMigrations)
|
||||
postMigration.Execute(Name, scope, originVersion, targetVersion, Logger);
|
||||
AfterMigrations(scope, logger);
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetStateValueKey(MigrationPlan plan) => "Umbraco.Core.Upgrader.State+" + plan.Name;
|
||||
/// <summary>
|
||||
/// Executes as part of the upgrade scope and before all migrations have executed.
|
||||
/// </summary>
|
||||
public virtual void BeforeMigrations(IScope scope, ILogger logger)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Executes as part of the upgrade scope and after all migrations have executed.
|
||||
/// </summary>
|
||||
public virtual void AfterMigrations(IScope scope, ILogger logger)
|
||||
{ }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Umbraco.Core.Persistence
|
||||
var (s, a) = sql.SqlContext.VisitDto(predicate, alias);
|
||||
return sql.Where(s, a);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Appends a WHERE clause to the Sql statement.
|
||||
/// </summary>
|
||||
@@ -1184,15 +1184,37 @@ namespace Umbraco.Core.Persistence
|
||||
return string.IsNullOrWhiteSpace(attr?.Name) ? column.Name : attr.Name;
|
||||
}
|
||||
|
||||
|
||||
internal static void WriteToConsole(this Sql sql)
|
||||
internal static string ToText(this Sql sql)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine(sql.SQL);
|
||||
var text = new StringBuilder();
|
||||
sql.ToText(text);
|
||||
return text.ToString();
|
||||
}
|
||||
|
||||
internal static void ToText(this Sql sql, StringBuilder text)
|
||||
{
|
||||
ToText(sql.SQL, sql.Arguments, text);
|
||||
}
|
||||
|
||||
internal static void ToText(string sql, object[] arguments, StringBuilder text)
|
||||
{
|
||||
text.AppendLine(sql);
|
||||
|
||||
if (arguments == null || arguments.Length == 0)
|
||||
return;
|
||||
|
||||
text.Append(" --");
|
||||
|
||||
var i = 0;
|
||||
foreach (var arg in sql.Arguments)
|
||||
Console.WriteLine($" @{i++}: {arg}");
|
||||
#endif
|
||||
foreach (var arg in arguments)
|
||||
{
|
||||
text.Append(" @");
|
||||
text.Append(i++);
|
||||
text.Append(":");
|
||||
text.Append(arg);
|
||||
}
|
||||
|
||||
text.AppendLine();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -30,10 +30,24 @@ namespace Umbraco.Core.Persistence
|
||||
Templates = new SqlTemplates(this);
|
||||
}
|
||||
|
||||
// fixme
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqlContext"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>Initializes an empty context which must be fully initialized using the
|
||||
/// <see cref="Initialize"/> method; this is done in <see cref="UmbracoDatabaseFactory"/>
|
||||
/// as soon as the factory is fully configured.</remarks>
|
||||
internal SqlContext()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this <see cref="SqlContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="sqlSyntax">The sql syntax provider.</param>
|
||||
/// <param name="pocoDataFactory">The Poco data factory.</param>
|
||||
/// <param name="databaseType">The database type.</param>
|
||||
/// <param name="mappers">The mappers.</param>
|
||||
/// <remarks>Fully initializes an initially empty context; this is done in <see cref="UmbracoDatabaseFactory"/>
|
||||
/// as soon as the factory is fully configured.</remarks>
|
||||
internal void Initialize(ISqlSyntaxProvider sqlSyntax, DatabaseType databaseType, IPocoDataFactory pocoDataFactory, IMapperCollection mappers = null)
|
||||
{
|
||||
// for tests
|
||||
|
||||
@@ -95,11 +95,10 @@ namespace Umbraco.Core.Persistence
|
||||
return new Sql<ISqlContext>(_sqlContext, isBuilt, _sql, args);
|
||||
}
|
||||
|
||||
internal void WriteToConsole()
|
||||
internal string ToText()
|
||||
{
|
||||
#if DEBUG
|
||||
new Sql<ISqlContext>(_sqlContext, _sql, _args.Values.ToArray()).WriteToConsole();
|
||||
#endif
|
||||
var sql = new Sql<ISqlContext>(_sqlContext, _sql, _args.Values.ToArray());
|
||||
return sql.ToText();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -246,26 +246,13 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
private string CommandToString(string sql, object[] args)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var text = new StringBuilder();
|
||||
#if DEBUG_DATABASES
|
||||
sb.Append(InstanceId);
|
||||
sb.Append(": ");
|
||||
text.Append(InstanceId);
|
||||
text.Append(": ");
|
||||
#endif
|
||||
sb.Append(sql);
|
||||
if (args.Length > 0)
|
||||
sb.Append(" --");
|
||||
var i = 0;
|
||||
foreach (var arg in args)
|
||||
{
|
||||
sb.Append(" @");
|
||||
sb.Append(i++);
|
||||
sb.Append(":");
|
||||
if (arg == DBNull.Value) sb.Append("<dbNull>");
|
||||
else if (arg == null) sb.Append("<null>");
|
||||
else sb.Append(arg);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
NPocoSqlExtensions.ToText(sql, args, text);
|
||||
return text.ToString();
|
||||
}
|
||||
|
||||
protected override void OnExecutedCommand(DbCommand cmd)
|
||||
|
||||
@@ -237,10 +237,10 @@ namespace Umbraco.Core.Runtime
|
||||
// and only these things - the rest should be composed in runtime components
|
||||
|
||||
// register basic things
|
||||
// logging, runtime state, configuration
|
||||
container.RegisterSingleton<IProfiler, LogProfiler>();
|
||||
container.RegisterSingleton<ProfilingLogger>();
|
||||
container.RegisterSingleton<IRuntimeState, RuntimeState>();
|
||||
|
||||
container.RegisterFrom<ConfigurationCompositionRoot>();
|
||||
|
||||
// register caches
|
||||
@@ -254,8 +254,8 @@ namespace Umbraco.Core.Runtime
|
||||
new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))));
|
||||
container.RegisterSingleton(f => f.GetInstance<CacheHelper>().RuntimeCache);
|
||||
|
||||
// register the plugin manager
|
||||
container.RegisterSingleton(f => new TypeLoader(f.GetInstance<IRuntimeCacheProvider>(), f.GetInstance<IGlobalSettings>(), f.GetInstance<ProfilingLogger>()));
|
||||
// register the type loader
|
||||
container.RegisterSingleton<TypeLoader>();
|
||||
|
||||
// register syntax providers - required by database factory
|
||||
container.Register<ISqlSyntaxProvider, MySqlSyntaxProvider>("MySqlSyntaxProvider");
|
||||
@@ -389,14 +389,14 @@ namespace Umbraco.Core.Runtime
|
||||
|
||||
protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger)
|
||||
{
|
||||
var umbracoPlan = new UmbracoPlan();
|
||||
var stateValueKey = Upgrader.GetStateValueKey(umbracoPlan);
|
||||
var upgrader = new UmbracoUpgrader();
|
||||
var stateValueKey = upgrader.StateValueKey;
|
||||
|
||||
// no scope, no service - just directly accessing the database
|
||||
using (var database = databaseFactory.CreateDatabase())
|
||||
{
|
||||
_state.CurrentMigrationState = KeyValueService.GetValue(database, stateValueKey);
|
||||
_state.FinalMigrationState = umbracoPlan.FinalState;
|
||||
_state.FinalMigrationState = upgrader.Plan.FinalState;
|
||||
}
|
||||
|
||||
logger.Debug<CoreRuntime>("Final upgrade state is {FinalMigrationState}, database contains {DatabaseState}", _state.FinalMigrationState, _state.CurrentMigrationState ?? "<null>");
|
||||
|
||||
@@ -5,6 +5,7 @@ using NUnit.Framework;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Migrations;
|
||||
using Umbraco.Core.Migrations.Install;
|
||||
using Umbraco.Core.Migrations.Upgrade;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -34,11 +35,12 @@ namespace Umbraco.Tests.Migrations
|
||||
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of<IKeyValueService>(), new PostMigrationCollection(Enumerable.Empty<IPostMigration>()), logger,
|
||||
new MigrationPlan("test", builder, logger)
|
||||
.Add<CreateTableOfTDtoMigration>(string.Empty, "done"));
|
||||
var upgrader = new Upgrader(
|
||||
new MigrationPlan("test")
|
||||
.From(string.Empty)
|
||||
.To<CreateTableOfTDtoMigration>("done"));
|
||||
|
||||
upgrader.Execute();
|
||||
upgrader.Execute(ScopeProvider, builder, Mock.Of<IKeyValueService>(), logger);
|
||||
|
||||
var helper = new DatabaseSchemaCreator(scope.Database, logger);
|
||||
var exists = helper.TableExists("umbracoUser");
|
||||
@@ -71,12 +73,13 @@ namespace Umbraco.Tests.Migrations
|
||||
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of<IKeyValueService>(), new PostMigrationCollection(Enumerable.Empty<IPostMigration>()), logger,
|
||||
new MigrationPlan("test", builder, logger)
|
||||
.Add<CreateTableOfTDtoMigration>(string.Empty, "a")
|
||||
.Add<DeleteKeysAndIndexesMigration>("a", "done"));
|
||||
var upgrader = new Upgrader(
|
||||
new MigrationPlan("test")
|
||||
.From(string.Empty)
|
||||
.To<CreateTableOfTDtoMigration>("a")
|
||||
.To<DeleteKeysAndIndexesMigration>("done"));
|
||||
|
||||
upgrader.Execute();
|
||||
upgrader.Execute(ScopeProvider, builder, Mock.Of<IKeyValueService>(), logger);
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
@@ -106,13 +109,14 @@ namespace Umbraco.Tests.Migrations
|
||||
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of<IKeyValueService>(), new PostMigrationCollection(Enumerable.Empty<IPostMigration>()), logger,
|
||||
new MigrationPlan("test", builder, logger)
|
||||
.Add<CreateTableOfTDtoMigration>(string.Empty, "a")
|
||||
.Add<DeleteKeysAndIndexesMigration>("a", "b")
|
||||
.Add<CreateKeysAndIndexesOfTDtoMigration>("b", "done"));
|
||||
var upgrader = new Upgrader(
|
||||
new MigrationPlan("test")
|
||||
.From(string.Empty)
|
||||
.To<CreateTableOfTDtoMigration>("a")
|
||||
.To<DeleteKeysAndIndexesMigration>("b")
|
||||
.To<CreateKeysAndIndexesOfTDtoMigration>("done"));
|
||||
|
||||
upgrader.Execute();
|
||||
upgrader.Execute(ScopeProvider, builder, Mock.Of<IKeyValueService>(), logger);
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
@@ -142,13 +146,14 @@ namespace Umbraco.Tests.Migrations
|
||||
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of<IKeyValueService>(), new PostMigrationCollection(Enumerable.Empty<IPostMigration>()), logger,
|
||||
new MigrationPlan("test", builder, logger)
|
||||
.Add<CreateTableOfTDtoMigration>(string.Empty, "a")
|
||||
.Add<DeleteKeysAndIndexesMigration>("a", "b")
|
||||
.Add<CreateKeysAndIndexesMigration>("b", "done"));
|
||||
var upgrader = new Upgrader(
|
||||
new MigrationPlan("test")
|
||||
.From(string.Empty)
|
||||
.To<CreateTableOfTDtoMigration>("a")
|
||||
.To<DeleteKeysAndIndexesMigration>("b")
|
||||
.To<CreateKeysAndIndexesMigration>("done"));
|
||||
|
||||
upgrader.Execute();
|
||||
upgrader.Execute(ScopeProvider, builder, Mock.Of<IKeyValueService>(), logger);
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
@@ -176,12 +181,13 @@ namespace Umbraco.Tests.Migrations
|
||||
|
||||
using (var scope = ScopeProvider.CreateScope())
|
||||
{
|
||||
var upgrader = new MigrationTests.TestUpgrader(ScopeProvider, builder, Mock.Of<IKeyValueService>(), new PostMigrationCollection(Enumerable.Empty<IPostMigration>()), logger,
|
||||
new MigrationPlan("test", builder, logger)
|
||||
.Add<CreateTableOfTDtoMigration>(string.Empty, "a")
|
||||
.Add<CreateColumnMigration>("a", "done"));
|
||||
var upgrader = new Upgrader(
|
||||
new MigrationPlan("test")
|
||||
.From(string.Empty)
|
||||
.To<CreateTableOfTDtoMigration>("a")
|
||||
.To<CreateColumnMigration>("done"));
|
||||
|
||||
upgrader.Execute();
|
||||
upgrader.Execute(ScopeProvider, builder, Mock.Of<IKeyValueService>(), logger);
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -46,13 +48,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", migrationBuilder, logger)
|
||||
var plan = new MigrationPlan("default")
|
||||
.From(string.Empty)
|
||||
.Chain<DeleteRedirectUrlTable>("{4A9A1A8F-0DA1-4BCF-AD06-C19D79152E35}")
|
||||
.Chain<NoopMigration>("VERSION.33");
|
||||
.To<DeleteRedirectUrlTable>("{4A9A1A8F-0DA1-4BCF-AD06-C19D79152E35}")
|
||||
.To<NoopMigration>("VERSION.33");
|
||||
|
||||
var kvs = Mock.Of<IKeyValueService>();
|
||||
Mock.Get(kvs).Setup(x => x.GetValue(It.IsAny<string>())).Returns<string>(k => k == "Umbraco.Tests.MigrationPlan" ? string.Empty : null);
|
||||
@@ -64,7 +63,7 @@ namespace Umbraco.Tests.Migrations
|
||||
var sourceState = kvs.GetValue("Umbraco.Tests.MigrationPlan") ?? string.Empty;
|
||||
|
||||
// execute plan
|
||||
state = plan.Execute(s, sourceState);
|
||||
state = plan.Execute(s, sourceState, migrationBuilder, logger);
|
||||
|
||||
// save new state
|
||||
kvs.SetValue("Umbraco.Tests.MigrationPlan", sourceState, state);
|
||||
@@ -81,63 +80,103 @@ namespace Umbraco.Tests.Migrations
|
||||
[Test]
|
||||
public void CanAddMigrations()
|
||||
{
|
||||
var plan = new MigrationPlan("default", Mock.Of<IMigrationBuilder>(), Mock.Of<ILogger>());
|
||||
plan.Add(string.Empty, "aaa");
|
||||
plan.Add("aaa", "bbb");
|
||||
plan.Add("bbb", "ccc");
|
||||
var plan = new MigrationPlan("default");
|
||||
plan
|
||||
.From(string.Empty)
|
||||
.To("aaa")
|
||||
.To("bbb")
|
||||
.To("ccc");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CannotTransitionToSameState()
|
||||
{
|
||||
var plan = new MigrationPlan("default", Mock.Of<IMigrationBuilder>(), Mock.Of<ILogger>());
|
||||
var plan = new MigrationPlan("default");
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
plan.Add("aaa", "aaa");
|
||||
plan.From("aaa").To("aaa");
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnlyOneTransitionPerState()
|
||||
{
|
||||
var plan = new MigrationPlan("default", Mock.Of<IMigrationBuilder>(), Mock.Of<ILogger>());
|
||||
plan.Add("aaa", "bbb");
|
||||
var plan = new MigrationPlan("default");
|
||||
plan.From("aaa").To("bbb");
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
plan.Add("aaa", "ccc");
|
||||
plan.From("aaa").To("ccc");
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CannotContainTwoMoreHeads()
|
||||
{
|
||||
var plan = new MigrationPlan("default", Mock.Of<IMigrationBuilder>(), Mock.Of<ILogger>());
|
||||
plan.Add(string.Empty, "aaa");
|
||||
plan.Add("aaa", "bbb");
|
||||
plan.Add("ccc", "ddd");
|
||||
var plan = new MigrationPlan("default");
|
||||
plan
|
||||
.From(string.Empty)
|
||||
.To("aaa")
|
||||
.To("bbb")
|
||||
.From("ccc")
|
||||
.To("ddd");
|
||||
Assert.Throws<Exception>(() => plan.Validate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CannotContainLoops()
|
||||
{
|
||||
var plan = new MigrationPlan("default", Mock.Of<IMigrationBuilder>(), Mock.Of<ILogger>());
|
||||
plan.Add(string.Empty, "aaa");
|
||||
plan.Add("aaa", "bbb");
|
||||
plan.Add("bbb", "ccc");
|
||||
plan.Add("ccc", "aaa");
|
||||
var plan = new MigrationPlan("default");
|
||||
plan
|
||||
.From("aaa")
|
||||
.To("bbb")
|
||||
.To("ccc")
|
||||
.To("aaa");
|
||||
Assert.Throws<Exception>(() => plan.Validate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ValidateUmbracoPlan()
|
||||
{
|
||||
var plan = new UmbracoPlan(Mock.Of<IMigrationBuilder>(), Mock.Of<ILogger>());
|
||||
var plan = new UmbracoPlan();
|
||||
plan.Validate();
|
||||
Console.WriteLine(plan.FinalState);
|
||||
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)
|
||||
|
||||
@@ -16,28 +16,32 @@ namespace Umbraco.Tests.Migrations
|
||||
[TestFixture]
|
||||
public class MigrationTests
|
||||
{
|
||||
public class TestUpgrader : Upgrader
|
||||
public class TestUpgraderWithPostMigrations : Upgrader
|
||||
{
|
||||
private readonly MigrationPlan _plan;
|
||||
private PostMigrationCollection _postMigrations;
|
||||
|
||||
public TestUpgrader(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, PostMigrationCollection postMigrations, ILogger logger, MigrationPlan plan)
|
||||
: base(scopeProvider, migrationBuilder, keyValueService, postMigrations, logger)
|
||||
public TestUpgraderWithPostMigrations(MigrationPlan plan)
|
||||
: base(plan)
|
||||
{ }
|
||||
|
||||
public void Execute(IScopeProvider scopeProvider, IMigrationBuilder migrationBuilder, IKeyValueService keyValueService, ILogger logger, PostMigrationCollection postMigrations)
|
||||
{
|
||||
_plan = plan;
|
||||
_postMigrations = postMigrations;
|
||||
Execute(scopeProvider, migrationBuilder, keyValueService, logger);
|
||||
}
|
||||
|
||||
protected override MigrationPlan GetPlan()
|
||||
public override void AfterMigrations(IScope scope, ILogger logger)
|
||||
{
|
||||
return _plan;
|
||||
}
|
||||
// run post-migrations
|
||||
var originVersion = new SemVersion(0);
|
||||
var targetVersion = new SemVersion(0);
|
||||
|
||||
protected override (SemVersion, SemVersion) GetVersions()
|
||||
{
|
||||
return (new SemVersion(0), new SemVersion(0));
|
||||
// run post-migrations
|
||||
foreach (var postMigration in _postMigrations)
|
||||
postMigration.Execute(Name, scope, originVersion, targetVersion, logger);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class TestScopeProvider : IScopeProvider
|
||||
{
|
||||
private readonly IScope _scope;
|
||||
|
||||
@@ -50,10 +50,9 @@ namespace Umbraco.Tests.Migrations
|
||||
var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of<IPocoDataFactory>());
|
||||
var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext };
|
||||
|
||||
var u1 = new MigrationTests.TestUpgrader(scopeProvider, builder, Mock.Of<IKeyValueService>(), posts, logger,
|
||||
new MigrationPlan("Test", builder, logger)
|
||||
.Add<NoopMigration>(string.Empty, "done"));
|
||||
u1.Execute();
|
||||
var u1 = new MigrationTests.TestUpgraderWithPostMigrations(
|
||||
new MigrationPlan("Test").From(string.Empty).To("done"));
|
||||
u1.Execute(scopeProvider, builder, Mock.Of<IKeyValueService>(), logger, posts);
|
||||
|
||||
Assert.AreEqual(1, changed1.CountExecuted);
|
||||
}
|
||||
@@ -94,18 +93,16 @@ namespace Umbraco.Tests.Migrations
|
||||
var sqlContext = new SqlContext(new SqlCeSyntaxProvider(), DatabaseType.SQLCe, Mock.Of<IPocoDataFactory>());
|
||||
var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext };
|
||||
|
||||
var u1 = new MigrationTests.TestUpgrader(scopeProvider, builder, Mock.Of<IKeyValueService>(), posts, logger,
|
||||
new MigrationPlan("Test1", builder, logger)
|
||||
.Add<NoopMigration>(string.Empty, "done"));
|
||||
u1.Execute();
|
||||
var u1 = new MigrationTests.TestUpgraderWithPostMigrations(
|
||||
new MigrationPlan("Test1").From(string.Empty).To("done"));
|
||||
u1.Execute(scopeProvider, builder, Mock.Of<IKeyValueService>(), logger, posts);
|
||||
|
||||
Assert.AreEqual(1, changed1.CountExecuted);
|
||||
Assert.AreEqual(0, changed2.CountExecuted);
|
||||
|
||||
var u2 = new MigrationTests.TestUpgrader(scopeProvider, builder, Mock.Of<IKeyValueService>(), posts, logger,
|
||||
new MigrationPlan("Test2", builder, logger)
|
||||
.Add<NoopMigration>(string.Empty, "done"));
|
||||
u2.Execute();
|
||||
var u2 = new MigrationTests.TestUpgraderWithPostMigrations(
|
||||
new MigrationPlan("Test2").From(string.Empty).To("done"));
|
||||
u2.Execute(scopeProvider, builder, Mock.Of<IKeyValueService>(), logger, posts);
|
||||
|
||||
Assert.AreEqual(1, changed1.CountExecuted);
|
||||
Assert.AreEqual(1, changed2.CountExecuted);
|
||||
|
||||
@@ -403,7 +403,6 @@ namespace Umbraco.Tests.Persistence.NPocoTests
|
||||
.From<Thing1Dto>()
|
||||
.Where<Thing1Dto>(x => x.Id == 1);
|
||||
|
||||
sql.WriteToConsole();
|
||||
var dto = scope.Database.Fetch<Thing1Dto>(sql).FirstOrDefault();
|
||||
Assert.IsNotNull(dto);
|
||||
Assert.AreEqual("one", dto.Name);
|
||||
@@ -415,7 +414,6 @@ namespace Umbraco.Tests.Persistence.NPocoTests
|
||||
//Assert.AreEqual("one", dto.Name);
|
||||
|
||||
var sql3 = new Sql(sql.SQL, 1);
|
||||
sql.WriteToConsole();
|
||||
dto = scope.Database.Fetch<Thing1Dto>(sql3).FirstOrDefault();
|
||||
Assert.IsNotNull(dto);
|
||||
Assert.AreEqual("one", dto.Name);
|
||||
|
||||
@@ -192,7 +192,6 @@ INNER JOIN [dto2] ON [dto1].[id] = [dto2].[dto1id]".NoCrLf(), sql.SQL.NoCrLf());
|
||||
var sql = Sql()
|
||||
.Update<DataTypeDto>(u => u.Set(x => x.EditorAlias, "Umbraco.ColorPicker"))
|
||||
.Where<DataTypeDto>(x => x.EditorAlias == "Umbraco.ColorPickerAlias");
|
||||
sql.WriteToConsole();
|
||||
}
|
||||
|
||||
[TableName("dto1")]
|
||||
|
||||
@@ -27,15 +27,9 @@ namespace Umbraco.Tests.Persistence.NPocoTests
|
||||
.From("zbThing1")
|
||||
.Where("id=@id", new { id = SqlTemplate.Arg("id") })).Sql(new { id = 1 });
|
||||
|
||||
sql.WriteToConsole();
|
||||
|
||||
var sql2 = sqlTemplates.Get("xxx", x => throw new InvalidOperationException("Should be cached.")).Sql(1);
|
||||
|
||||
sql2.WriteToConsole();
|
||||
|
||||
var sql3 = sqlTemplates.Get("xxx", x => throw new InvalidOperationException("Should be cached.")).Sql(new { id = 1 });
|
||||
|
||||
sql3.WriteToConsole();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -75,8 +69,8 @@ namespace Umbraco.Tests.Persistence.NPocoTests
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual(123, sql.Arguments[0]);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => template.Sql(new { xvalue = 123 }).WriteToConsole());
|
||||
Assert.Throws<InvalidOperationException>(() => template.Sql(new { value = 123, xvalue = 456 }).WriteToConsole());
|
||||
Assert.Throws<InvalidOperationException>(() => template.Sql(new { xvalue = 123 }));
|
||||
Assert.Throws<InvalidOperationException>(() => template.Sql(new { value = 123, xvalue = 456 }));
|
||||
|
||||
var i = 666;
|
||||
|
||||
@@ -121,8 +115,8 @@ namespace Umbraco.Tests.Persistence.NPocoTests
|
||||
Assert.AreEqual(1, sql.Arguments.Length);
|
||||
Assert.AreEqual(123, sql.Arguments[0]);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => template.Sql(new { j = 123 }).WriteToConsole());
|
||||
Assert.Throws<InvalidOperationException>(() => template.Sql(new { i = 123, j = 456 }).WriteToConsole());
|
||||
Assert.Throws<InvalidOperationException>(() => template.Sql(new { j = 123 }));
|
||||
Assert.Throws<InvalidOperationException>(() => template.Sql(new { i = 123, j = 456 }));
|
||||
|
||||
// now with more arguments
|
||||
|
||||
|
||||
@@ -305,12 +305,10 @@ namespace Umbraco.Tests.Persistence.NPocoTests
|
||||
.From<UserLoginDto>()
|
||||
.Where<UserLoginDto>(x => x.SessionId == sessionId);
|
||||
|
||||
sql.WriteToConsole();
|
||||
Assert.AreEqual("SELECT * FROM [umbracoUserLogin] WHERE (([umbracoUserLogin].[sessionId] = @0))", sql.SQL.NoCrLf());
|
||||
|
||||
sql = sql.ForUpdate();
|
||||
|
||||
sql.WriteToConsole();
|
||||
Assert.AreEqual("SELECT * FROM [umbracoUserLogin] WITH (UPDLOCK) WHERE (([umbracoUserLogin].[sessionId] = @0))", sql.SQL.NoCrLf());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,6 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
var translator = new SqlTranslator<IContent>(sql, query);
|
||||
var result = translator.Translate();
|
||||
|
||||
result.WriteToConsole();
|
||||
|
||||
Assert.AreEqual("-1,1046,1076,1089%", result.Arguments[0]);
|
||||
Assert.AreEqual(1046, result.Arguments[1]);
|
||||
Assert.AreEqual(true, result.Arguments[2]);
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
using Semver;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Migrations;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Web.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// This will execute after upgrading to remove any xml cache for media that are currently in the bin
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will execute for specific versions -
|
||||
///
|
||||
/// * If current is less than or equal to 7.0.0
|
||||
/// </remarks>
|
||||
public class ClearMediaXmlCacheForDeletedItemsAfterUpgrade : IPostMigration
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ClearMediaXmlCacheForDeletedItemsAfterUpgrade(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger)
|
||||
{
|
||||
if (name != Constants.System.UmbracoUpgradePlanName) return;
|
||||
|
||||
var target70 = new SemVersion(7 /*, 0, 0*/);
|
||||
|
||||
if (originVersion <= target70)
|
||||
{
|
||||
//This query is structured to work with MySql, SQLCE and SqlServer:
|
||||
// http://issues.umbraco.org/issue/U4-3876
|
||||
|
||||
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 = scope.Database.Execute(sql);
|
||||
|
||||
_logger.Info<ClearMediaXmlCacheForDeletedItemsAfterUpgrade>("Cleared {Total} items from the media xml cache that were trashed and not meant to be there", count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using System;
|
||||
using NPoco;
|
||||
using Semver;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Migrations;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Web.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates the built in list view data types
|
||||
/// </summary>
|
||||
public class EnsureDefaultListViewDataTypesCreated : IPostMigration
|
||||
{
|
||||
public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger)
|
||||
{
|
||||
if (name != Constants.System.UmbracoUpgradePlanName) 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<NodeDto>(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 = -1, 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 = -1, 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 = -1, 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))));
|
||||
|
||||
const string memberListViewConfiguration = "{\"pageSize\":10,\"orderBy\":Name,\"orderDirection\":asc,includeProperties:[{\"alias\":\"email\",\"isSystem\":1},{\"alias\":\"username\",\"isSystem\":1},{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1}]}";
|
||||
|
||||
scope.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.DefaultContentListView, EditorAlias = Constants.PropertyEditors.Aliases.ListView, DbType = "Nvarchar" });
|
||||
scope.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.DefaultMediaListView, EditorAlias = Constants.PropertyEditors.Aliases.ListView, DbType = "Nvarchar" });
|
||||
scope.Database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.DefaultMembersListView, EditorAlias = Constants.PropertyEditors.Aliases.ListView, DbType = "Nvarchar", Configuration = memberListViewConfiguration });
|
||||
}
|
||||
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))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using System.IO;
|
||||
using Semver;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Migrations;
|
||||
using Umbraco.Core.Migrations.Upgrade;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Web.Migrations
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// When upgrading version 7.3 the migration MigrateStylesheetDataToFile will execute but we don't want to overwrite the developers
|
||||
/// files during the migration since other parts of the migration might fail. So once the migration is complete, we'll then copy over the temp
|
||||
/// files that this migration created over top of the developer's files. We'll also create a backup of their files.
|
||||
/// </summary>
|
||||
public sealed class OverwriteStylesheetFilesFromTempFiles : IPostMigration
|
||||
{
|
||||
public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger)
|
||||
{
|
||||
if (name != Constants.System.UmbracoUpgradePlanName) return;
|
||||
|
||||
var target73 = new SemVersion(7, 3, 0);
|
||||
|
||||
if (originVersion <= target73)
|
||||
{
|
||||
var tempCssFolder = IOHelper.MapPath("~/App_Data/TEMP/CssMigration/");
|
||||
var cssFolder = IOHelper.MapPath("~/css");
|
||||
if (Directory.Exists(tempCssFolder))
|
||||
{
|
||||
var files = Directory.GetFiles(tempCssFolder, "*.css", SearchOption.AllDirectories);
|
||||
foreach (var file in files)
|
||||
{
|
||||
var relativePath = file.TrimStart(tempCssFolder).TrimStart("\\");
|
||||
var cssFilePath = Path.Combine(cssFolder, relativePath);
|
||||
if (File.Exists(cssFilePath))
|
||||
{
|
||||
//backup
|
||||
var targetPath = Path.Combine(tempCssFolder, relativePath.EnsureEndsWith(".bak"));
|
||||
logger.Info<OverwriteStylesheetFilesFromTempFiles>("CSS file is being backed up from {CssFilePath}, to {TargetPath} before being migrated to new format", cssFilePath, targetPath);
|
||||
File.Copy(cssFilePath, targetPath, true);
|
||||
}
|
||||
|
||||
//ensure the sub folder eixts
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(cssFilePath));
|
||||
File.Copy(file, cssFilePath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using Semver;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Migrations;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.PublishedCache.XmlPublishedCache;
|
||||
|
||||
namespace Umbraco.Web.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Rebuilds the Xml caches after upgrading.
|
||||
/// This will execute after upgrading to rebuild the xml cache
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>This cannot execute as part of a DB migration since it needs access to services and repositories.</para>
|
||||
/// <para>Executes for:
|
||||
/// - Media Xml : if current is less than, or equal to, 7.0.0 (superceeded by the next rule)
|
||||
/// - Media & Content Xml : if current is less than, or equal to, 7.3.0 - because 7.3.0 adds .Key to cached items
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class RebuildXmlCachesAfterUpgrade : IPostMigration
|
||||
{
|
||||
public void Execute(string name, IScope scope, SemVersion originVersion, SemVersion targetVersion, ILogger logger)
|
||||
{
|
||||
if (name != Constants.System.UmbracoUpgradePlanName) return;
|
||||
|
||||
var v730 = new SemVersion(new Version(7, 3, 0));
|
||||
|
||||
var doMedia = originVersion < v730;
|
||||
var doContent = originVersion < v730;
|
||||
|
||||
if (doMedia)
|
||||
{
|
||||
// fixme - maintain - for backward compatibility?! or replace with...?!
|
||||
//var mediaService = (MediaService) ApplicationContext.Current.Services.MediaService;
|
||||
//mediaService.RebuildXmlStructures();
|
||||
|
||||
var svc = Current.PublishedSnapshotService as PublishedSnapshotService;
|
||||
svc?.RebuildMediaXml();
|
||||
|
||||
// note: not re-indexing medias?
|
||||
}
|
||||
|
||||
if (doContent)
|
||||
{
|
||||
// fixme - maintain - for backward compatibility?! or replace with...?!
|
||||
//var contentService = (ContentService) ApplicationContext.Current.Services.ContentService;
|
||||
//contentService.RebuildXmlStructures();
|
||||
|
||||
var svc = Current.PublishedSnapshotService as PublishedSnapshotService;
|
||||
svc?.RebuildContentAndPreviewXml();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -835,9 +835,6 @@
|
||||
<Compile Include="Security\UmbracoBackOfficeCookieAuthOptions.cs" />
|
||||
<Compile Include="Scheduling\TaskAndFactoryExtensions.cs" />
|
||||
<Compile Include="Migrations\ClearCsrfCookiesAfterUpgrade.cs" />
|
||||
<Compile Include="Migrations\ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs" />
|
||||
<Compile Include="Migrations\EnsureListViewDataTypeIsCreated.cs" />
|
||||
<Compile Include="Migrations\OverwriteStylesheetFilesFromTempFiles.cs" />
|
||||
<Compile Include="Components\NotificationsComponent.cs" />
|
||||
<Compile Include="TagQuery.cs" />
|
||||
<Compile Include="Trees\CoreTreeAttribute.cs" />
|
||||
@@ -1005,7 +1002,6 @@
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UI\JavaScript\ServerVariablesParser.cs" />
|
||||
<Compile Include="Migrations\RebuildXmlCachesAfterUpgrade.cs" />
|
||||
<Compile Include="Components\PublicAccessComponent.cs" />
|
||||
<Compile Include="UI\Bundles\JsJQueryCore.cs" />
|
||||
<Compile Include="UI\Bundles\JsUmbracoApplicationUI.cs" />
|
||||
|
||||
Reference in New Issue
Block a user