diff --git a/build/RevertToCleanInstall.bat b/build/RevertToCleanInstall.bat
new file mode 100644
index 0000000000..893b7216ee
--- /dev/null
+++ b/build/RevertToCleanInstall.bat
@@ -0,0 +1,98 @@
+@ECHO OFF
+
+:choice
+set /P c=WARNING! Are you sure you want to continue, this will remove all package files, view files, sqlce database, etc... Press 'Y' to auto-remove all files/folders, 'N' to cancel or 'C' to prompt for each folder removal?
+if /I "%c%" EQU "C" goto :prompt
+if /I "%c%" EQU "Y" goto :auto
+if /I "%c%" EQU "N" goto :exit
+goto :choice
+
+
+:prompt
+
+echo Current folder: %CD%
+
+echo Removing sqlce database
+del ..\src\Umbraco.Web.UI\App_Data\Umbraco.sdf
+
+echo Resetting installedPackages.config
+echo ^^^ >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
+
+echo Removing plugin cache files
+del ..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*
+
+echo Removing log files
+del ..\src\Umbraco.Web.UI\App_Data\Logs\*.*
+
+echo Removing xslt files
+del ..\src\Umbraco.Web.UI\Xslt\*.*
+
+echo Removing user control files
+del ..\src\Umbraco.Web.UI\UserControls\*.*
+
+echo Removing view files
+del ..\src\Umbraco.Web.UI\Views\*.*
+
+echo Removing razor files
+del ..\src\Umbraco.Web.UI\MacroScripts\*.*
+
+echo Removing media files
+del ..\src\Umbraco.Web.UI\Media\*.*
+
+echo Removing script files
+del ..\src\Umbraco.Web.UI\Scripts\*.*
+
+echo Removing css files
+del ..\src\Umbraco.Web.UI\Css\*.*
+
+echo "Umbraco install reverted to clean install"
+pause
+exit
+
+
+
+:auto
+
+echo Current folder: %CD%
+
+echo Removing sqlce database
+del ..\src\Umbraco.Web.UI\App_Data\Umbraco.sdf
+
+echo Resetting installedPackages.config
+echo ^^^ >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
+
+echo Removing plugin cache files
+FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*) DO DEL %%A
+
+echo Removing log files
+FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\Logs\*.*) DO DEL %%A
+
+echo Removing xslt files
+FOR %%A IN (..\src\Umbraco.Web.UI\Xslt\*.*) DO DEL %%A
+
+echo Removing user control files
+FOR %%A IN (..\src\Umbraco.Web.UI\UserControls\*.*) DO DEL %%A
+
+echo Removing view files
+FOR %%A IN (..\src\Umbraco.Web.UI\Views\*.*) DO DEL %%A
+
+echo Removing razor files
+FOR %%A IN (..\src\Umbraco.Web.UI\MacroScripts\*.*) DO DEL %%A
+
+echo Removing media files
+FOR %%A IN (..\src\Umbraco.Web.UI\Media\*.*) DO DEL %%A
+
+echo Removing script files
+FOR %%A IN (..\src\Umbraco.Web.UI\Scripts\*.*) DO DEL %%A
+
+echo Removing css files
+FOR %%A IN (..\src\Umbraco.Web.UI\Css\*.*) DO DEL %%A
+
+echo "Umbraco install reverted to clean install"
+pause
+exit
+
+
+
+:exit
+exit
\ No newline at end of file
diff --git a/src/Umbraco.Core/DisposableTimer.cs b/src/Umbraco.Core/DisposableTimer.cs
index 26a7875559..f2a6904b9f 100644
--- a/src/Umbraco.Core/DisposableTimer.cs
+++ b/src/Umbraco.Core/DisposableTimer.cs
@@ -41,6 +41,17 @@ namespace Umbraco.Core
return new DisposableTimer(callback);
}
+ public static DisposableTimer TraceDuration(Func startMessage, Func completeMessage)
+ {
+ return TraceDuration(typeof(T), startMessage, completeMessage);
+ }
+
+ public static DisposableTimer TraceDuration(Type loggerType, Func startMessage, Func completeMessage)
+ {
+ LogHelper.Debug(loggerType, startMessage);
+ return new DisposableTimer(x => LogHelper.Info(loggerType, () => completeMessage() + " (took " + x + "ms)"));
+ }
+
///
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
///
diff --git a/src/Umbraco.Core/PluginManager.cs b/src/Umbraco.Core/PluginManager.cs
index e8670992b7..b0de40416b 100644
--- a/src/Umbraco.Core/PluginManager.cs
+++ b/src/Umbraco.Core/PluginManager.cs
@@ -68,6 +68,14 @@ namespace Umbraco.Core
Directory.CreateDirectory(_tempFolder);
}
+ //this is a check for legacy changes, before we didn't store the TypeResolutionKind in the file which was a mistake,
+ //so we need to detect if the old file is there without this attribute, if it is then we delete it
+ if (DetectLegacyPluginListFile())
+ {
+ var filePath = GetPluginListFilePath();
+ File.Delete(filePath);
+ }
+
if (detectCodeChanges)
{
//first check if the cached hash is 0, if it is then we ne
@@ -120,6 +128,7 @@ namespace Umbraco.Core
#region Hash checking methods
+
///
/// Returns a bool if the assemblies in the /bin have changed since they were last hashed.
///
@@ -228,9 +237,9 @@ namespace Umbraco.Core
///
///
///
- internal Attempt> TryGetCachedPluginsFromFile()
+ internal Attempt> TryGetCachedPluginsFromFile(TypeResolutionKind resolutionType)
{
- var filePath = Path.Combine(_tempFolder, "umbraco-plugins.list");
+ var filePath = GetPluginListFilePath();
if (!File.Exists(filePath))
return Attempt>.False;
@@ -257,9 +266,12 @@ namespace Umbraco.Core
var typeElement = xml.Root.Elements()
.SingleOrDefault(x =>
x.Name.LocalName == "baseType"
- && ((string) x.Attribute("type")) == typeof (T).FullName);
+ && ((string) x.Attribute("type")) == typeof (T).FullName
+ && ((string) x.Attribute("resolutionType")) == resolutionType.ToString());
+
+ //return false but specify this exception type so we can detect it
if (typeElement == null)
- return Attempt>.False;
+ return new Attempt>(new CachedPluginNotFoundInFile());
//return success
return new Attempt>(
@@ -267,10 +279,52 @@ namespace Umbraco.Core
typeElement.Elements("add")
.Select(x => (string) x.Attribute("type")));
}
- catch (Exception)
+ catch (Exception ex)
{
//if the file is corrupted, etc... return false
- return Attempt>.False;
+ return new Attempt>(ex);
+ }
+ }
+
+ private string GetPluginListFilePath()
+ {
+ return Path.Combine(_tempFolder, "umbraco-plugins.list");
+ }
+
+ ///
+ /// This will return true if the plugin list file is a legacy one
+ ///
+ ///
+ ///
+ /// This method exists purely due to an error in 4.11. We were writing the plugin list file without the
+ /// type resolution kind which will have caused some problems. Now we detect this legacy file and if it is detected
+ /// we remove it so it can be recreated properly.
+ ///
+ internal bool DetectLegacyPluginListFile()
+ {
+ var filePath = GetPluginListFilePath();
+ if (!File.Exists(filePath))
+ return false;
+
+ try
+ {
+ var xml = XDocument.Load(filePath);
+ if (xml.Root == null)
+ return false;
+
+ var typeElement = xml.Root.Elements()
+ .FirstOrDefault(x => x.Name.LocalName == "baseType");
+
+ if (typeElement == null)
+ return false;
+
+ //now check if the typeElement is missing the resolutionType attribute
+ return typeElement.Attributes().All(x => x.Name.LocalName != "resolutionType");
+ }
+ catch (Exception)
+ {
+ //if the file is corrupted, etc... return true so it is removed
+ return true;
}
}
@@ -279,7 +333,8 @@ namespace Umbraco.Core
///
///
///
- ///
+ ///
+ ///
/// THIS METHOD IS NOT THREAD SAFE
///
///
@@ -292,9 +347,9 @@ namespace Umbraco.Core
///
/// ]]>
///
- internal void UpdateCachedPluginsFile(IEnumerable typesFound)
+ internal void UpdateCachedPluginsFile(IEnumerable typesFound, TypeResolutionKind resolutionType)
{
- var filePath = Path.Combine(_tempFolder, "umbraco-plugins.list");
+ var filePath = GetPluginListFilePath();
XDocument xml;
try
{
@@ -316,11 +371,15 @@ namespace Umbraco.Core
var typeElement = xml.Root.Elements()
.SingleOrDefault(x =>
x.Name.LocalName == "baseType"
- && ((string)x.Attribute("type")) == typeof(T).FullName);
+ && ((string)x.Attribute("type")) == typeof(T).FullName
+ && ((string)x.Attribute("resolutionType")) == resolutionType.ToString());
+
if (typeElement == null)
{
//create the type element
- typeElement = new XElement("baseType", new XAttribute("type", typeof(T).FullName));
+ typeElement = new XElement("baseType",
+ new XAttribute("type", typeof(T).FullName),
+ new XAttribute("resolutionType", resolutionType.ToString()));
//then add it to the root
xml.Root.Add(typeElement);
}
@@ -486,9 +545,11 @@ namespace Umbraco.Core
{
using (var readLock = new UpgradeableReadLock(_lock))
{
+ var typesFound = new List();
+
using (DisposableTimer.TraceDuration(
- String.Format("Starting resolution types of {0}", typeof(T).FullName),
- String.Format("Completed resolution of types of {0}", typeof(T).FullName)))
+ () => String.Format("Starting resolution types of {0}", typeof(T).FullName),
+ () => String.Format("Completed resolution of types of {0}, found {1}", typeof(T).FullName, typesFound.Count)))
{
//check if the TypeList already exists, if so return it, if not we'll create it
var typeList = _types.SingleOrDefault(x => x.IsTypeList(resolutionType));
@@ -501,46 +562,59 @@ namespace Umbraco.Core
typeList = new TypeList(resolutionType);
//we first need to look into our cache file (this has nothing to do with the 'cacheResult' parameter which caches in memory).
- if (!HaveAssembliesChanged)
+ //if assemblies have not changed and the cache file actually exists, then proceed to try to lookup by the cache file.
+ if (!HaveAssembliesChanged && File.Exists(GetPluginListFilePath()))
{
- var fileCacheResult = TryGetCachedPluginsFromFile();
- if (fileCacheResult.Success)
+ var fileCacheResult = TryGetCachedPluginsFromFile(resolutionType);
+
+ //here we need to identify if the CachedPluginNotFoundInFile was the exception, if it was then we need to re-scan
+ //in some cases the plugin will not have been scanned for on application startup, but the assemblies haven't changed
+ //so in this instance there will never be a result.
+ if (fileCacheResult.Error != null && fileCacheResult.Error is CachedPluginNotFoundInFile)
{
- var successfullyLoadedFromCache = true;
- //we have a previous cache for this so we don't need to scan we just load what has been found in the file
- foreach(var t in fileCacheResult.Result)
- {
- try
- {
- //we use the build manager to ensure we get all types loaded, this is slightly slower than
- //Type.GetType but if the types in the assembly aren't loaded yet then we have problems with that.
- var type = BuildManager.GetType(t, true);
- typeList.AddType(type);
- }
- catch (Exception ex)
- {
- //if there are any exceptions loading types, we have to exist, this should never happen so
- //we will need to revert to scanning for types.
- successfullyLoadedFromCache = false;
- LogHelper.Error("Could not load a cached plugin type: " + t + " now reverting to re-scanning assemblies for the base type: " + typeof (T).FullName, ex);
- break;
- }
- }
- if (!successfullyLoadedFromCache )
- {
- //we need to manually load by scanning if loading from the file was not successful.
- LoadViaScanningAndUpdateCacheFile(typeList, finder);
- }
- else
- {
- LogHelper.Debug("Loaded plugin types " + typeof(T).FullName + " from persisted cache");
- }
+ //we don't have a cache for this so proceed to look them up by scanning
+ LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder);
}
+ else
+ {
+ if (fileCacheResult.Success)
+ {
+ var successfullyLoadedFromCache = true;
+ //we have a previous cache for this so we don't need to scan we just load what has been found in the file
+ foreach (var t in fileCacheResult.Result)
+ {
+ try
+ {
+ //we use the build manager to ensure we get all types loaded, this is slightly slower than
+ //Type.GetType but if the types in the assembly aren't loaded yet then we have problems with that.
+ var type = BuildManager.GetType(t, true);
+ typeList.AddType(type);
+ }
+ catch (Exception ex)
+ {
+ //if there are any exceptions loading types, we have to exist, this should never happen so
+ //we will need to revert to scanning for types.
+ successfullyLoadedFromCache = false;
+ LogHelper.Error("Could not load a cached plugin type: " + t + " now reverting to re-scanning assemblies for the base type: " + typeof(T).FullName, ex);
+ break;
+ }
+ }
+ if (!successfullyLoadedFromCache)
+ {
+ //we need to manually load by scanning if loading from the file was not successful.
+ LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder);
+ }
+ else
+ {
+ LogHelper.Debug("Loaded plugin types " + typeof(T).FullName + " from persisted cache");
+ }
+ }
+ }
}
else
{
//we don't have a cache for this so proceed to look them up by scanning
- LoadViaScanningAndUpdateCacheFile(typeList, finder);
+ LoadViaScanningAndUpdateCacheFile(typeList, resolutionType, finder);
}
//only add the cache if we are to cache the results
@@ -550,8 +624,10 @@ namespace Umbraco.Core
_types.Add(typeList);
}
}
- return typeList.GetTypes();
+ typesFound = typeList.GetTypes().ToList();
}
+
+ return typesFound;
}
}
@@ -560,18 +636,19 @@ namespace Umbraco.Core
/// Once the results are loaded, we update the cached type xml file
///
///
+ ///
///
///
/// THIS METHODS IS NOT THREAD SAFE
///
- private void LoadViaScanningAndUpdateCacheFile(TypeList typeList, Func> finder)
+ private void LoadViaScanningAndUpdateCacheFile(TypeList typeList, TypeResolutionKind resolutionKind, Func> finder)
{
//we don't have a cache for this so proceed to look them up by scanning
foreach (var t in finder())
{
typeList.AddType(t);
- }
- UpdateCachedPluginsFile(typeList.GetTypes());
+ }
+ UpdateCachedPluginsFile(typeList.GetTypes(), resolutionKind);
}
///
@@ -683,6 +760,16 @@ namespace Umbraco.Core
return _types;
}
}
+
+ ///
+ /// This class is used simply to determine that a plugin was not found in the cache plugin list with the specified
+ /// TypeResolutionKind.
+ ///
+ internal class CachedPluginNotFoundInFile : Exception
+ {
+
+ }
+
#endregion
}
}
diff --git a/src/Umbraco.Tests/PluginManagerTests.cs b/src/Umbraco.Tests/PluginManagerTests.cs
index 0c47c04ba2..4dbaae98de 100644
--- a/src/Umbraco.Tests/PluginManagerTests.cs
+++ b/src/Umbraco.Tests/PluginManagerTests.cs
@@ -8,6 +8,7 @@ using System.Web.Compilation;
using NUnit.Framework;
using SqlCE4Umbraco;
using Umbraco.Core;
+using Umbraco.Core.IO;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using umbraco;
@@ -148,6 +149,34 @@ namespace Umbraco.Tests
// Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds);
//}
+ [Test]
+ public void Detect_Legacy_Plugin_File_List()
+ {
+ var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
+ var manager = new PluginManager(false);
+ var filePath = Path.Combine(tempFolder, "umbraco-plugins.list");
+ File.WriteAllText(filePath, @"
+
+
+
+
+");
+
+ Assert.IsTrue(manager.DetectLegacyPluginListFile());
+
+ File.Delete(filePath);
+
+ //now create a valid one
+ File.WriteAllText(filePath, @"
+
+
+
+
+");
+
+ Assert.IsFalse(manager.DetectLegacyPluginListFile());
+ }
+
[Test]
public void Create_Cached_Plugin_File()
{
@@ -155,10 +184,15 @@ namespace Umbraco.Tests
var manager = new PluginManager(false);
//yes this is silly, none of these types inherit from string, but this is just to test the xml file format
- manager.UpdateCachedPluginsFile(types);
+ manager.UpdateCachedPluginsFile(types, PluginManager.TypeResolutionKind.FindAllTypes);
+
+ var plugins = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAllTypes);
+ var diffType = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAttributedTypes);
- var plugins = manager.TryGetCachedPluginsFromFile();
Assert.IsTrue(plugins.Success);
+ //this will be false since there is no cache of that type resolution kind
+ Assert.IsFalse(diffType.Success);
+
Assert.AreEqual(3, plugins.Result.Count());
var shouldContain = types.Select(x => x.AssemblyQualifiedName);
//ensure they are all found
@@ -206,11 +240,11 @@ namespace Umbraco.Tests
var hash3 = PluginManager.GetAssembliesHash(list3);
//Assert
-
- //both should be the same since we only create the hash based on the unique folder of the list passed in, yet
- //all files will exist in those folders still
- Assert.AreEqual(hash1, hash2);
+ Assert.AreNotEqual(hash1, hash2);
Assert.AreNotEqual(hash1, hash3);
+ Assert.AreNotEqual(hash2, hash3);
+
+ Assert.AreEqual(hash1, PluginManager.GetAssembliesHash(list1));
}
[Test]
diff --git a/src/umbraco.cms/businesslogic/Packager/Installer.cs b/src/umbraco.cms/businesslogic/Packager/Installer.cs
index b58f20290b..9f4376fdee 100644
--- a/src/umbraco.cms/businesslogic/Packager/Installer.cs
+++ b/src/umbraco.cms/businesslogic/Packager/Installer.cs
@@ -13,7 +13,8 @@ using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
-
+using Umbraco.Core;
+using Umbraco.Core.Logging;
using umbraco.cms.businesslogic.web;
using umbraco.cms.businesslogic.propertytype;
using umbraco.BusinessLogic;
@@ -154,29 +155,34 @@ namespace umbraco.cms.businesslogic.packager
///
public string Import(string InputFile)
{
- string tempDir = "";
- if (File.Exists(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile)))
- {
- FileInfo fi = new FileInfo(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile));
- // Check if the file is a valid package
- if (fi.Extension.ToLower() == ".umb")
- {
- try
- {
- tempDir = unPack(fi.FullName);
- LoadConfig(tempDir);
- }
- catch (Exception unpackE)
- {
- throw new Exception("Error unpacking extension...", unpackE);
- }
- }
- else
- throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download.");
- }
- else
- throw new Exception("Error - file not found. Could find file named '" + IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile) + "'");
- return tempDir;
+ using (DisposableTimer.DebugDuration(
+ () => "Importing package file " + InputFile,
+ () => "Package file " + InputFile + "imported"))
+ {
+ string tempDir = "";
+ if (File.Exists(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile)))
+ {
+ FileInfo fi = new FileInfo(IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile));
+ // Check if the file is a valid package
+ if (fi.Extension.ToLower() == ".umb")
+ {
+ try
+ {
+ tempDir = unPack(fi.FullName);
+ LoadConfig(tempDir);
+ }
+ catch (Exception unpackE)
+ {
+ throw new Exception("Error unpacking extension...", unpackE);
+ }
+ }
+ else
+ throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download.");
+ }
+ else
+ throw new Exception("Error - file not found. Could find file named '" + IOHelper.MapPath(SystemDirectories.Data + Path.DirectorySeparatorChar + InputFile) + "'");
+ return tempDir;
+ }
}
@@ -220,218 +226,259 @@ namespace umbraco.cms.businesslogic.packager
return insPack.Data.Id;
}
- public void InstallFiles(int packageId, string tempDir) {
+ public void InstallFiles(int packageId, string tempDir)
+ {
+ using (DisposableTimer.DebugDuration(
+ () => "Installing package files for package id " + packageId + " into temp folder " + tempDir,
+ () => "Package file installation complete for package id " + packageId))
+ {
+ //retrieve the manifest to continue installation
+ packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId);
- //retrieve the manifest to continue installation
- packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId);
+ // Move files
+ //string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath;
+ string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
- // Move files
- //string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath;
- string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//file"))
+ {
+ //we enclose the whole file-moving to ensure that the entire installer doesn't crash
+ try
+ {
+ String destPath = getFileName(basePath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")));
+ String sourceFile = getFileName(tempDir, xmlHelper.GetNodeValue(n.SelectSingleNode("guid")));
+ String destFile = getFileName(destPath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//file")) {
- //we enclose the whole file-moving to ensure that the entire installer doesn't crash
- try {
- String destPath = getFileName(basePath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")));
- String sourceFile = getFileName(tempDir, xmlHelper.GetNodeValue(n.SelectSingleNode("guid")));
- String destFile = getFileName(destPath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
+ // Create the destination directory if it doesn't exist
+ if (!Directory.Exists(destPath))
+ Directory.CreateDirectory(destPath);
+ //If a file with this name exists, delete it
+ else if (File.Exists(destFile))
+ File.Delete(destFile);
- // Create the destination directory if it doesn't exist
- if (!Directory.Exists(destPath))
- Directory.CreateDirectory(destPath);
- //If a file with this name exists, delete it
- else if (File.Exists(destFile))
- File.Delete(destFile);
+ // Move the file
+ File.Move(sourceFile, destFile);
- // Move the file
- File.Move(sourceFile, destFile);
+ //PPH log file install
+ insPack.Data.Files.Add(xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
+ }
+ catch (Exception ex)
+ {
+ Log.Add(LogTypes.Error, -1, "Package install error: " + ex.ToString());
+ }
+ }
- //PPH log file install
- insPack.Data.Files.Add(xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + xmlHelper.GetNodeValue(n.SelectSingleNode("orgName")));
- } catch (Exception ex) {
- Log.Add(LogTypes.Error, -1, "Package install error: " + ex.ToString());
- }
- }
-
- insPack.Save();
+ insPack.Save();
+ }
}
public void InstallBusinessLogic(int packageId, string tempDir) {
-
- //retrieve the manifest to continue installation
- packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId);
- bool saveNeeded = false;
- //Install DataTypes
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//DataType")) {
- cms.businesslogic.datatype.DataTypeDefinition newDtd = cms.businesslogic.datatype.DataTypeDefinition.Import(n);
+ using (DisposableTimer.DebugDuration(
+ () => "Installing business logic for package id " + packageId + " into temp folder " + tempDir,
+ () => "Package business logic installation complete for package id " + packageId))
+ {
+ //retrieve the manifest to continue installation
+ packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId);
+ bool saveNeeded = false;
- if (newDtd != null) {
- insPack.Data.DataTypes.Add(newDtd.Id.ToString());
- saveNeeded = true;
- }
- }
+ //Install DataTypes
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//DataType"))
+ {
+ cms.businesslogic.datatype.DataTypeDefinition newDtd = cms.businesslogic.datatype.DataTypeDefinition.Import(n);
- if (saveNeeded) {insPack.Save(); saveNeeded = false;}
+ if (newDtd != null)
+ {
+ insPack.Data.DataTypes.Add(newDtd.Id.ToString());
+ saveNeeded = true;
+ }
+ }
- //Install languages
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//Language")) {
- language.Language newLang = language.Language.Import(n);
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- if (newLang != null) {
- insPack.Data.Languages.Add(newLang.id.ToString());
- saveNeeded = true;
- }
- }
+ //Install languages
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//Language"))
+ {
+ language.Language newLang = language.Language.Import(n);
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (newLang != null)
+ {
+ insPack.Data.Languages.Add(newLang.id.ToString());
+ saveNeeded = true;
+ }
+ }
- //Install dictionary items
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("./DictionaryItems/DictionaryItem")) {
- Dictionary.DictionaryItem newDi = Dictionary.DictionaryItem.Import(n);
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- if (newDi != null) {
- insPack.Data.DictionaryItems.Add(newDi.id.ToString());
- saveNeeded = true;
- }
- }
+ //Install dictionary items
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("./DictionaryItems/DictionaryItem"))
+ {
+ Dictionary.DictionaryItem newDi = Dictionary.DictionaryItem.Import(n);
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (newDi != null)
+ {
+ insPack.Data.DictionaryItems.Add(newDi.id.ToString());
+ saveNeeded = true;
+ }
+ }
- // Install macros
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//macro")) {
- cms.businesslogic.macro.Macro m = cms.businesslogic.macro.Macro.Import(n);
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- if (m != null) {
- insPack.Data.Macros.Add(m.Id.ToString());
- saveNeeded = true;
- }
- }
+ // Install macros
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//macro"))
+ {
+ cms.businesslogic.macro.Macro m = cms.businesslogic.macro.Macro.Import(n);
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (m != null)
+ {
+ insPack.Data.Macros.Add(m.Id.ToString());
+ saveNeeded = true;
+ }
+ }
- // Get current user, with a fallback
- User u = new User(0);
- if (!string.IsNullOrEmpty(BasePages.UmbracoEnsuredPage.umbracoUserContextID)) {
- if (BasePages.UmbracoEnsuredPage.ValidateUserContextID(BasePages.UmbracoEnsuredPage.umbracoUserContextID)) {
- u = User.GetCurrent();
- }
- }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+
+ // Get current user, with a fallback
+ User u = new User(0);
+ if (!string.IsNullOrEmpty(BasePages.UmbracoEnsuredPage.umbracoUserContextID))
+ {
+ if (BasePages.UmbracoEnsuredPage.ValidateUserContextID(BasePages.UmbracoEnsuredPage.umbracoUserContextID))
+ {
+ u = User.GetCurrent();
+ }
+ }
- // Add Templates
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template")) {
- var t = Template.Import(n, u);
-
- insPack.Data.Templates.Add(t.Id.ToString());
+ // Add Templates
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template"))
+ {
+ var t = Template.Import(n, u);
- saveNeeded = true;
- }
+ insPack.Data.Templates.Add(t.Id.ToString());
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ saveNeeded = true;
+ }
+
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- //NOTE: SD: I'm pretty sure the only thing the below script does is ensure that the Master template Id is set
- // in the database, but this is also duplicating the saving of the design content since the above Template.Import
- // already does this. I've left this for now because I'm not sure the reprocussions of removing it but seems there
- // is a lot of excess database calls happening here.
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template")) {
- string master = xmlHelper.GetNodeValue(n.SelectSingleNode("Master"));
- template.Template t = template.Template.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Alias")));
- if (master.Trim() != "") {
- template.Template masterTemplate = template.Template.GetByAlias(master);
- if (masterTemplate != null) {
- t.MasterTemplate = template.Template.GetByAlias(master).Id;
- //SD: This appears to always just save an empty template because the design isn't set yet
- // this fixes an issue now that we have MVC because if there is an empty template and MVC is
- // the default, it will create a View not a master page and then the system will try to route via
- // MVC which means that the package will not work anymore.
- // The code below that imports the templates should suffice because it's actually importing
- // template data not just blank data.
+ //NOTE: SD: I'm pretty sure the only thing the below script does is ensure that the Master template Id is set
+ // in the database, but this is also duplicating the saving of the design content since the above Template.Import
+ // already does this. I've left this for now because I'm not sure the reprocussions of removing it but seems there
+ // is a lot of excess database calls happening here.
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template"))
+ {
+ string master = xmlHelper.GetNodeValue(n.SelectSingleNode("Master"));
+ template.Template t = template.Template.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Alias")));
+ if (master.Trim() != "")
+ {
+ template.Template masterTemplate = template.Template.GetByAlias(master);
+ if (masterTemplate != null)
+ {
+ t.MasterTemplate = template.Template.GetByAlias(master).Id;
+ //SD: This appears to always just save an empty template because the design isn't set yet
+ // this fixes an issue now that we have MVC because if there is an empty template and MVC is
+ // the default, it will create a View not a master page and then the system will try to route via
+ // MVC which means that the package will not work anymore.
+ // The code below that imports the templates should suffice because it's actually importing
+ // template data not just blank data.
- //if (UmbracoSettings.UseAspNetMasterPages)
- // t.SaveMasterPageFile(t.Design);
- }
- }
- // Master templates can only be generated when their master is known
- if (UmbracoSettings.UseAspNetMasterPages) {
- t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design")));
- t.SaveMasterPageFile(t.Design);
- }
- }
+ //if (UmbracoSettings.UseAspNetMasterPages)
+ // t.SaveMasterPageFile(t.Design);
+ }
+ }
+ // Master templates can only be generated when their master is known
+ if (UmbracoSettings.UseAspNetMasterPages)
+ {
+ t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design")));
+ t.SaveMasterPageFile(t.Design);
+ }
+ }
- // Add documenttypes
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType")) {
- ImportDocumentType(n, u, false);
- saveNeeded = true;
- }
+ // Add documenttypes
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType"))
+ {
+ ImportDocumentType(n, u, false);
+ saveNeeded = true;
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- // Add documenttype structure
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType")) {
- DocumentType dt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Alias")));
- if (dt != null) {
- ArrayList allowed = new ArrayList();
- foreach (XmlNode structure in n.SelectNodes("Structure/DocumentType")) {
- DocumentType dtt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(structure));
- if(dtt != null)
- allowed.Add(dtt.Id);
- }
+ // Add documenttype structure
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType"))
+ {
+ DocumentType dt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Alias")));
+ if (dt != null)
+ {
+ ArrayList allowed = new ArrayList();
+ foreach (XmlNode structure in n.SelectNodes("Structure/DocumentType"))
+ {
+ DocumentType dtt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(structure));
+ if (dtt != null)
+ allowed.Add(dtt.Id);
+ }
- int[] adt = new int[allowed.Count];
- for (int i = 0; i < allowed.Count; i++)
- adt[i] = (int)allowed[i];
- dt.AllowedChildContentTypeIDs = adt;
+ int[] adt = new int[allowed.Count];
+ for (int i = 0; i < allowed.Count; i++)
+ adt[i] = (int)allowed[i];
+ dt.AllowedChildContentTypeIDs = adt;
- //PPH we log the document type install here.
- insPack.Data.Documenttypes.Add(dt.Id.ToString());
- saveNeeded = true;
- }
- }
+ //PPH we log the document type install here.
+ insPack.Data.Documenttypes.Add(dt.Id.ToString());
+ saveNeeded = true;
+ }
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- // Stylesheets
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Stylesheets/Stylesheet")) {
- StyleSheet s = StyleSheet.Import(n, u);
+ // Stylesheets
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Stylesheets/Stylesheet"))
+ {
+ StyleSheet s = StyleSheet.Import(n, u);
- insPack.Data.Stylesheets.Add(s.Id.ToString());
- saveNeeded = true;
- }
+ insPack.Data.Stylesheets.Add(s.Id.ToString());
+ saveNeeded = true;
+ }
- if (saveNeeded) { insPack.Save(); saveNeeded = false; }
+ if (saveNeeded) { insPack.Save(); saveNeeded = false; }
- // Documents
- foreach (XmlElement n in _packageConfig.DocumentElement.SelectNodes("Documents/DocumentSet [@importMode = 'root']/*")) {
- insPack.Data.ContentNodeId = cms.businesslogic.web.Document.Import(-1, u, n).ToString();
- }
+ // Documents
+ foreach (XmlElement n in _packageConfig.DocumentElement.SelectNodes("Documents/DocumentSet [@importMode = 'root']/*"))
+ {
+ insPack.Data.ContentNodeId = cms.businesslogic.web.Document.Import(-1, u, n).ToString();
+ }
- //Package Actions
- foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action")) {
+ //Package Actions
+ foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action"))
+ {
- if (n.Attributes["undo"] == null || n.Attributes["undo"].Value == "true") {
- insPack.Data.Actions += n.OuterXml;
- Log.Add(LogTypes.Debug, -1, HttpUtility.HtmlEncode(n.OuterXml));
- }
+ if (n.Attributes["undo"] == null || n.Attributes["undo"].Value == "true")
+ {
+ insPack.Data.Actions += n.OuterXml;
+ Log.Add(LogTypes.Debug, -1, HttpUtility.HtmlEncode(n.OuterXml));
+ }
- if (n.Attributes["runat"] != null && n.Attributes["runat"].Value == "install") {
- try {
- packager.PackageAction.RunPackageAction(insPack.Data.Name, n.Attributes["alias"].Value, n);
- } catch {
+ if (n.Attributes["runat"] != null && n.Attributes["runat"].Value == "install")
+ {
+ try
+ {
+ packager.PackageAction.RunPackageAction(insPack.Data.Name, n.Attributes["alias"].Value, n);
+ }
+ catch
+ {
- }
- }
- }
+ }
+ }
+ }
- // Trigger update of Apps / Trees config.
- // (These are ApplicationStartupHandlers so just instantiating them will trigger them)
- new ApplicationRegistrar();
- new ApplicationTreeRegistrar();
+ // Trigger update of Apps / Trees config.
+ // (These are ApplicationStartupHandlers so just instantiating them will trigger them)
+ new ApplicationRegistrar();
+ new ApplicationTreeRegistrar();
- insPack.Save();
+ insPack.Save();
+ }
}
public void InstallCleanUp(int packageId, string tempDir) {
diff --git a/src/umbraco.sln b/src/umbraco.sln
index bbf29e5a99..87674b9000 100644
--- a/src/umbraco.sln
+++ b/src/umbraco.sln
@@ -6,6 +6,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{2849E9D4
ProjectSection(SolutionItems) = preProject
..\build\Build.bat = ..\build\Build.bat
..\build\Build.proj = ..\build\Build.proj
+ ..\build\RevertToCleanInstall.bat = ..\build\RevertToCleanInstall.bat
umbraco.presentation.targets = umbraco.presentation.targets
EndProjectSection
EndProject