Merge branch temp8 into temp8-3675-variant-tags

This commit is contained in:
Stephan
2018-12-12 16:04:58 +01:00
31 changed files with 480 additions and 644 deletions

View File

@@ -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()
{

View File

@@ -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();

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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>";

View File

@@ -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 });
}

View File

@@ -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();

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
{
@@ -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.

View File

@@ -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}");
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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)
{ }
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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)

View File

@@ -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>");

View File

@@ -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();
}
}

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;
@@ -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)

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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")]

View File

@@ -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

View File

@@ -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());
}
}

View File

@@ -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]);

View File

@@ -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);
}
}
}
}

View File

@@ -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))));
}
}
}
}

View File

@@ -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);
}
}
}
}
}
}

View File

@@ -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();
}
}
}
}

View File

@@ -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" />