Updates the upgrader to ensure that the latest migrations are run if they don't exist, fixes the migration runner null check, adds test to subtract a revision number from a Version object.

This commit is contained in:
Shannon
2015-06-23 18:10:50 +02:00
parent c204741fb9
commit 869e0dcbd2
10 changed files with 148 additions and 12 deletions

View File

@@ -579,10 +579,11 @@ namespace Umbraco.Core
message = GetResultMessageForMySql();
var schemaResult = ValidateDatabaseSchema();
var installedVersion = schemaResult.DetermineInstalledVersion();
var installedSchemaVersion = schemaResult.DetermineInstalledVersion();
//If Configuration Status is empty and the determined version is "empty" its a new install - otherwise upgrade the existing
if (string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) && installedVersion.Equals(new Version(0, 0, 0)))
if (string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) && installedSchemaVersion.Equals(new Version(0, 0, 0)))
{
var helper = new DatabaseSchemaHelper(database, _logger, SqlSyntax);
helper.CreateDatabaseSchema(true, applicationContext);
@@ -634,14 +635,30 @@ namespace Umbraco.Core
var message = GetResultMessageForMySql();
var schemaResult = ValidateDatabaseSchema();
var installedVersion = schemaResult.DetermineInstalledVersion();
var installedSchemaVersion = 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 Version(0, 0, 0) && installedSchemaVersion > new Version(0, 0, 0))
{
//set the installedMigrationVersion to be one less than the target so the latest migrations are guaranteed to execute
installedMigrationVersion = targetVersion.SubtractRevision();
}
//DO the upgrade!
var currentVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus)
? installedVersion
: new Version(GlobalSettings.ConfigurationStatus);
var targetVersion = UmbracoVersion.Current;
//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[] { new Version(GlobalSettings.ConfigurationStatus), installedMigrationVersion }.Min();
var runner = new MigrationRunner(migrationEntryService, _logger, currentVersion, targetVersion, GlobalSettings.UmbracoMigrationName);
var upgraded = runner.Execute(database, true);
message = message + "<p>Upgrade completed!</p>";

View File

@@ -8,7 +8,13 @@ namespace Umbraco.Core.Persistence.Factories
{
public MigrationEntry BuildEntity(MigrationDto dto)
{
var model = new MigrationEntry(dto.Id, dto.CreateDate, dto.Name, Version.Parse(dto.Version));
Version parsed;
if (Version.TryParse(dto.Version, out parsed) == false)
{
throw new FormatException("Cannot parse the version string in the database to a real Version object: " + dto.Version);
}
var model = new MigrationEntry(dto.Id, dto.CreateDate, dto.Name, parsed);
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
model.ResetDirtyProperties(false);

View File

@@ -5,6 +5,7 @@ using System.Text;
using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Services;
namespace Umbraco.Core.Persistence.Migrations.Initial
{
@@ -35,7 +36,20 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
internal IEnumerable<DbIndexDefinition> DbIndexDefinitions { get; set; }
/// <summary>
/// Determines the version of the currently installed database.
/// Checks in the db which version is installed based on the migrations that have been run
/// </summary>
/// <param name="migrationEntryService"></param>
/// <returns></returns>
public Version DetermineInstalledVersionByMigrations(IMigrationEntryService migrationEntryService)
{
var allMigrations = migrationEntryService.GetAll(GlobalSettings.UmbracoMigrationName);
var mostrecent = allMigrations.OrderByDescending(x => x.Version).Select(x => x.Version).FirstOrDefault();
return mostrecent ?? new Version(0, 0, 0);
}
/// <summary>
/// Determines the version of the currently installed database by detecting the current database structure
/// </summary>
/// <returns>
/// A <see cref="Version"/> with Major and Minor values for

View File

@@ -29,7 +29,7 @@ namespace Umbraco.Core.Persistence.Migrations
[Obsolete("Use the ctor that specifies all dependencies instead")]
public MigrationRunner(ILogger logger, Version currentVersion, Version targetVersion, string productName)
: this(logger, currentVersion, targetVersion, productName, Enumerable.Empty<IMigration>().ToArray())
: this(logger, currentVersion, targetVersion, productName, null)
{
}
@@ -53,7 +53,8 @@ namespace Umbraco.Core.Persistence.Migrations
_currentVersion = currentVersion;
_targetVersion = targetVersion;
_productName = productName;
_migrations = migrations;
//ensure this is null if there aren't any
_migrations = migrations.Length == 0 ? null : migrations;
}
/// <summary>

View File

@@ -30,7 +30,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("lastPasswordChangeDate")) == false)
Create.Column("lastPasswordChangeDate").OnTable("umbracoUser").AsDateTime().Nullable();
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("lastLoginDate")) == false);
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("lastLoginDate")) == false)
Create.Column("lastLoginDate").OnTable("umbracoUser").AsDateTime().Nullable();
}

View File

@@ -1313,6 +1313,7 @@
<Compile Include="StringExtensions.cs" />
<Compile Include="UriExtensions.cs" />
<Compile Include="SystemUtilities.cs" />
<Compile Include="VersionExtensions.cs" />
<Compile Include="WriteLock.cs" />
<Compile Include="XmlExtensions.cs" />
<Compile Include="XmlHelper.cs" />

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core
{
internal static class VersionExtensions
{
public static Version SubtractRevision(this Version version)
{
var parts = new List<int>(new[] {version.Major, version.Minor, version.Build, version.Revision});
//remove all prefixed zero parts
while (parts[0] <= 0)
{
parts.RemoveAt(0);
if (parts.Count == 0) break;
}
for (int index = 0; index < parts.Count; index++)
{
var part = parts[index];
if (part <= 0)
{
parts.RemoveAt(index);
index++;
}
else
{
//break when there isn't a zero part
break;
}
}
if (parts.Count == 0) throw new InvalidOperationException("Cannot subtract a revision from a zero version");
var lastNonZero = parts.FindLastIndex(i => i > 0);
//subtract 1 from the last non-zero
parts[lastNonZero] = parts[lastNonZero] - 1;
//the last non zero is actually the revision so we can just return
if (lastNonZero == (parts.Count -1))
{
return FromList(parts);
}
//the last non zero isn't the revision so the remaining zero's need to be replaced with int.max
for (var i = lastNonZero + 1; i < parts.Count; i++)
{
parts[i] = int.MaxValue;
}
return FromList(parts);
}
private static Version FromList(IList<int> parts)
{
while (parts.Count < 4)
{
parts.Insert(0, 0);
}
return new Version(parts[0], parts[1], parts[2], parts[3]);
}
}
}

View File

@@ -12,7 +12,7 @@ using Umbraco.Core.IO;
namespace Umbraco.Core
{
/// <summary>
/// <summary>
/// The XmlHelper class contains general helper methods for working with xml in umbraco.
/// </summary>
public class XmlHelper

View File

@@ -551,6 +551,7 @@
<Compile Include="TestHelpers\FakeHttpContextFactory.cs" />
<Compile Include="Plugins\TypeFinderTests.cs" />
<Compile Include="Routing\UmbracoModuleTests.cs" />
<Compile Include="VersionExtensionTests.cs" />
<Compile Include="XmlExtensionsTests.cs" />
<Compile Include="XmlHelperTests.cs" />
</ItemGroup>

View File

@@ -0,0 +1,30 @@
using System;
using NUnit.Framework;
using Umbraco.Core;
namespace Umbraco.Tests
{
[TestFixture]
public class VersionExtensionTests
{
[TestCase(1, 0, 0, 0, "0.2147483647.2147483647.2147483647")]
[TestCase(1, 1, 0, 0, "1.0.2147483647.2147483647")]
[TestCase(1, 1, 1, 0, "1.1.0.2147483647")]
[TestCase(1, 1, 1, 1, "1.1.1.0")]
[TestCase(0, 1, 0, 0, "0.0.2147483647.2147483647")]
[TestCase(0, 1, 1, 0, "0.1.0.2147483647")]
[TestCase(0, 1, 1, 1, "0.1.1.0")]
[TestCase(0, 0, 1, 0, "0.0.0.2147483647")]
[TestCase(0, 0, 1, 1, "0.0.1.0")]
[TestCase(0, 0, 0, 1, "0.0.0.0")]
[TestCase(7, 3, 0, 0, "7.2.2147483647.2147483647")]
public void Subract_Revision(int major, int minor, int build, int rev, string outcome)
{
var version = new Version(major, minor, build, rev);
var result = version.SubtractRevision();
Assert.AreEqual(new Version(outcome), result);
}
}
}