AB3869 move packages to abstractions
This commit is contained in:
@@ -1,196 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Packaging;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Umbraco.Core.Packaging
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses the xml document contained in a compiled (zip) Umbraco package
|
||||
/// </summary>
|
||||
internal class CompiledPackageXmlParser
|
||||
{
|
||||
private readonly ConflictingPackageData _conflictingPackageData;
|
||||
|
||||
public CompiledPackageXmlParser(ConflictingPackageData conflictingPackageData)
|
||||
{
|
||||
_conflictingPackageData = conflictingPackageData;
|
||||
}
|
||||
|
||||
public CompiledPackage ToCompiledPackage(XDocument xml, FileInfo packageFile, string applicationRootFolder)
|
||||
{
|
||||
if (xml == null) throw new ArgumentNullException(nameof(xml));
|
||||
if (xml.Root == null) throw new ArgumentException(nameof(xml), "The xml document is invalid");
|
||||
if (xml.Root.Name != "umbPackage") throw new FormatException("The xml document is invalid");
|
||||
|
||||
var info = xml.Root.Element("info");
|
||||
if (info == null) throw new FormatException("The xml document is invalid");
|
||||
var package = info.Element("package");
|
||||
if (package == null) throw new FormatException("The xml document is invalid");
|
||||
var author = info.Element("author");
|
||||
if (author == null) throw new FormatException("The xml document is invalid");
|
||||
var requirements = package.Element("requirements");
|
||||
if (requirements == null) throw new FormatException("The xml document is invalid");
|
||||
|
||||
var def = new CompiledPackage
|
||||
{
|
||||
PackageFile = packageFile,
|
||||
Name = package.Element("name")?.Value,
|
||||
Author = author.Element("name")?.Value,
|
||||
AuthorUrl = author.Element("website")?.Value,
|
||||
Contributors = info.Element("contributors")?.Elements("contributor").Select(x => x.Value).ToList() ?? new List<string>(),
|
||||
Version = package.Element("version")?.Value,
|
||||
Readme = info.Element("readme")?.Value,
|
||||
License = package.Element("license")?.Value,
|
||||
LicenseUrl = package.Element("license")?.AttributeValue<string>("url"),
|
||||
Url = package.Element("url")?.Value,
|
||||
IconUrl = package.Element("iconUrl")?.Value,
|
||||
UmbracoVersion = new Version((int)requirements.Element("major"), (int)requirements.Element("minor"), (int)requirements.Element("patch")),
|
||||
UmbracoVersionRequirementsType = requirements.AttributeValue<string>("type").IsNullOrWhiteSpace() ? RequirementsType.Legacy : Enum<RequirementsType>.Parse(requirements.AttributeValue<string>("type"), true),
|
||||
PackageView = xml.Root.Element("view")?.Value,
|
||||
Actions = xml.Root.Element("Actions")?.ToString(SaveOptions.None) ?? "<Actions></Actions>", //take the entire outer xml value
|
||||
Files = xml.Root.Element("files")?.Elements("file")?.Select(CompiledPackageFile.Create).ToList() ?? new List<CompiledPackageFile>(),
|
||||
Macros = xml.Root.Element("Macros")?.Elements("macro") ?? Enumerable.Empty<XElement>(),
|
||||
Templates = xml.Root.Element("Templates")?.Elements("Template") ?? Enumerable.Empty<XElement>(),
|
||||
Stylesheets = xml.Root.Element("Stylesheets")?.Elements("styleSheet") ?? Enumerable.Empty<XElement>(),
|
||||
DataTypes = xml.Root.Element("DataTypes")?.Elements("DataType") ?? Enumerable.Empty<XElement>(),
|
||||
Languages = xml.Root.Element("Languages")?.Elements("Language") ?? Enumerable.Empty<XElement>(),
|
||||
DictionaryItems = xml.Root.Element("DictionaryItems")?.Elements("DictionaryItem") ?? Enumerable.Empty<XElement>(),
|
||||
DocumentTypes = xml.Root.Element("DocumentTypes")?.Elements("DocumentType") ?? Enumerable.Empty<XElement>(),
|
||||
Documents = xml.Root.Element("Documents")?.Elements("DocumentSet")?.Select(CompiledPackageDocument.Create) ?? Enumerable.Empty<CompiledPackageDocument>(),
|
||||
};
|
||||
|
||||
def.Warnings = GetPreInstallWarnings(def, applicationRootFolder);
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
private PreInstallWarnings GetPreInstallWarnings(CompiledPackage package, string applicationRootFolder)
|
||||
{
|
||||
var sourceDestination = ExtractSourceDestinationFileInformation(package.Files);
|
||||
|
||||
var installWarnings = new PreInstallWarnings
|
||||
{
|
||||
ConflictingMacros = _conflictingPackageData.FindConflictingMacros(package.Macros),
|
||||
ConflictingTemplates = _conflictingPackageData.FindConflictingTemplates(package.Templates),
|
||||
ConflictingStylesheets = _conflictingPackageData.FindConflictingStylesheets(package.Stylesheets),
|
||||
UnsecureFiles = FindUnsecureFiles(sourceDestination),
|
||||
FilesReplaced = FindFilesToBeReplaced(sourceDestination, applicationRootFolder)
|
||||
};
|
||||
|
||||
return installWarnings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a tuple of the zip file's unique file name and it's application relative path
|
||||
/// </summary>
|
||||
/// <param name="packageFiles"></param>
|
||||
/// <returns></returns>
|
||||
public (string packageUniqueFile, string appRelativePath)[] ExtractSourceDestinationFileInformation(IEnumerable<CompiledPackageFile> packageFiles)
|
||||
{
|
||||
return packageFiles
|
||||
.Select(e =>
|
||||
{
|
||||
var fileName = PrepareAsFilePathElement(e.OriginalName);
|
||||
var relativeDir = UpdatePathPlaceholders(PrepareAsFilePathElement(e.OriginalPath));
|
||||
var relativePath = Path.Combine(relativeDir, fileName);
|
||||
return (e.UniqueFileName, relativePath);
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
private IEnumerable<string> FindFilesToBeReplaced(IEnumerable<(string packageUniqueFile, string appRelativePath)> sourceDestination, string applicationRootFolder)
|
||||
{
|
||||
return sourceDestination.Where(sd => File.Exists(Path.Combine(applicationRootFolder, sd.appRelativePath)))
|
||||
.Select(x => x.appRelativePath)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private IEnumerable<string> FindUnsecureFiles(IEnumerable<(string packageUniqueFile, string appRelativePath)> sourceDestinationPair)
|
||||
{
|
||||
return sourceDestinationPair.Where(sd => IsFileDestinationUnsecure(sd.appRelativePath))
|
||||
.Select(x => x.appRelativePath)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private bool IsFileDestinationUnsecure(string destination)
|
||||
{
|
||||
var unsecureDirNames = new[] { "bin", "app_code" };
|
||||
if (unsecureDirNames.Any(ud => destination.StartsWith(ud, StringComparison.InvariantCultureIgnoreCase)))
|
||||
return true;
|
||||
|
||||
string extension = Path.GetExtension(destination);
|
||||
return extension != null && extension.Equals(".dll", StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
private static string PrepareAsFilePathElement(string pathElement)
|
||||
{
|
||||
return pathElement.TrimStart(new[] { '\\', '/', '~' }).Replace("/", "\\");
|
||||
}
|
||||
|
||||
private static string UpdatePathPlaceholders(string path)
|
||||
{
|
||||
if (path.Contains("[$"))
|
||||
{
|
||||
//this is experimental and undocumented...
|
||||
path = path.Replace("[$UMBRACO]", Current.Configs.Global().UmbracoPath);
|
||||
path = path.Replace("[$CONFIG]", Constants.SystemDirectories.Config);
|
||||
path = path.Replace("[$DATA]", Constants.SystemDirectories.Data);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the package actions stored in the package definition
|
||||
/// </summary>
|
||||
/// <param name="actionsElement"></param>
|
||||
/// <param name="packageName"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<PackageAction> GetPackageActions(XElement actionsElement, string packageName)
|
||||
{
|
||||
if (actionsElement == null) return Enumerable.Empty<PackageAction>();
|
||||
|
||||
//invariant check ... because people can really enter anything :/
|
||||
if (!string.Equals("actions", actionsElement.Name.LocalName, StringComparison.InvariantCultureIgnoreCase))
|
||||
throw new FormatException("Must be \"<actions>\" as root");
|
||||
|
||||
if (!actionsElement.HasElements) return Enumerable.Empty<PackageAction>();
|
||||
|
||||
var actionElementName = actionsElement.Elements().First().Name.LocalName;
|
||||
|
||||
//invariant check ... because people can really enter anything :/
|
||||
if (!string.Equals("action", actionElementName, StringComparison.InvariantCultureIgnoreCase))
|
||||
throw new FormatException("Must be \"<action\" as element");
|
||||
|
||||
return actionsElement.Elements(actionElementName)
|
||||
.Select(e =>
|
||||
{
|
||||
var aliasAttr = e.Attribute("alias") ?? e.Attribute("Alias"); //allow both ... because people can really enter anything :/
|
||||
if (aliasAttr == null)
|
||||
throw new ArgumentException("missing \"alias\" attribute in alias element", nameof(actionsElement));
|
||||
|
||||
var packageAction = new PackageAction
|
||||
{
|
||||
XmlData = e,
|
||||
Alias = aliasAttr.Value,
|
||||
PackageName = packageName,
|
||||
};
|
||||
|
||||
var attr = e.Attribute("runat") ?? e.Attribute("Runat"); //allow both ... because people can really enter anything :/
|
||||
|
||||
if (attr != null && Enum.TryParse(attr.Value, true, out ActionRunAt runAt)) { packageAction.RunAt = runAt; }
|
||||
|
||||
attr = e.Attribute("undo") ?? e.Attribute("Undo"); //allow both ... because people can really enter anything :/
|
||||
|
||||
if (attr != null && bool.TryParse(attr.Value, out var undo)) { packageAction.Undo = undo; }
|
||||
|
||||
return packageAction;
|
||||
}).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Umbraco.Core.Models.Packaging;
|
||||
|
||||
namespace Umbraco.Core.Packaging
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the storage of created package definitions
|
||||
/// </summary>
|
||||
public interface ICreatedPackagesRepository : IPackageDefinitionRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates the package file and returns it's physical path
|
||||
/// </summary>
|
||||
/// <param name="definition"></param>
|
||||
string ExportPackage(PackageDefinition definition);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Packaging
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the storage of installed package definitions
|
||||
/// </summary>
|
||||
public interface IInstalledPackagesRepository : IPackageDefinitionRepository
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.Packaging;
|
||||
|
||||
namespace Umbraco.Core.Packaging
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines methods for persisting package definitions to storage
|
||||
/// </summary>
|
||||
public interface IPackageDefinitionRepository
|
||||
{
|
||||
IEnumerable<PackageDefinition> GetAll();
|
||||
PackageDefinition GetById(int id);
|
||||
void Delete(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Persists a package definition to storage
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// true if creating/updating the package was successful, otherwise false
|
||||
/// </returns>
|
||||
bool SavePackage(PackageDefinition definition);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models.Packaging;
|
||||
|
||||
namespace Umbraco.Core.Packaging
|
||||
{
|
||||
public interface IPackageInstallation
|
||||
{
|
||||
/// <summary>
|
||||
/// This will run the uninstall sequence for this <see cref="PackageDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="packageDefinition"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
UninstallationSummary UninstallPackage(PackageDefinition packageDefinition, int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Installs a packages data and entities
|
||||
/// </summary>
|
||||
/// <param name="packageDefinition"></param>
|
||||
/// <param name="compiledPackage"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
InstallationSummary InstallPackageData(PackageDefinition packageDefinition, CompiledPackage compiledPackage, int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Installs a packages files
|
||||
/// </summary>
|
||||
/// <param name="packageDefinition"></param>
|
||||
/// <param name="compiledPackage"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<string> InstallPackageFiles(PackageDefinition packageDefinition, CompiledPackage compiledPackage, int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the package (zip) file and returns the <see cref="CompiledPackage"/> model
|
||||
/// </summary>
|
||||
/// <param name="packageFile"></param>
|
||||
/// <returns></returns>
|
||||
CompiledPackage ReadPackage(FileInfo packageFile);
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,10 @@ using System.Web;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core.Collections;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Models.Packaging;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Packaging;
|
||||
|
||||
namespace Umbraco.Core.Packaging
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="PackageDefinition"/> to and from XML
|
||||
/// </summary>
|
||||
public class PackageDefinitionXmlParser
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public PackageDefinitionXmlParser(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public PackageDefinition ToPackageDefinition(XElement xml)
|
||||
{
|
||||
if (xml == null) return null;
|
||||
|
||||
var retVal = new PackageDefinition
|
||||
{
|
||||
Id = xml.AttributeValue<int>("id"),
|
||||
Name = xml.AttributeValue<string>("name") ?? string.Empty,
|
||||
PackagePath = xml.AttributeValue<string>("packagePath") ?? string.Empty,
|
||||
Version = xml.AttributeValue<string>("version") ?? string.Empty,
|
||||
Url = xml.AttributeValue<string>("url") ?? string.Empty,
|
||||
PackageId = xml.AttributeValue<Guid>("packageGuid"),
|
||||
IconUrl = xml.AttributeValue<string>("iconUrl") ?? string.Empty,
|
||||
UmbracoVersion = xml.AttributeValue<Version>("umbVersion"),
|
||||
PackageView = xml.AttributeValue<string>("view") ?? string.Empty,
|
||||
License = xml.Element("license")?.Value ?? string.Empty,
|
||||
LicenseUrl = xml.Element("license")?.AttributeValue<string>("url") ?? string.Empty,
|
||||
Author = xml.Element("author")?.Value ?? string.Empty,
|
||||
AuthorUrl = xml.Element("author")?.AttributeValue<string>("url") ?? string.Empty,
|
||||
Contributors = xml.Element("contributors")?.Elements("contributor").Select(x => x.Value).ToList() ?? new List<string>(),
|
||||
Readme = xml.Element("readme")?.Value ?? string.Empty,
|
||||
Actions = xml.Element("actions")?.ToString(SaveOptions.None) ?? "<actions></actions>", //take the entire outer xml value
|
||||
ContentNodeId = xml.Element("content")?.AttributeValue<string>("nodeId") ?? string.Empty,
|
||||
ContentLoadChildNodes = xml.Element("content")?.AttributeValue<bool>("loadChildNodes") ?? false,
|
||||
Macros = xml.Element("macros")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
Templates = xml.Element("templates")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
Stylesheets = xml.Element("stylesheets")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
DocumentTypes = xml.Element("documentTypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
Languages = xml.Element("languages")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
DictionaryItems = xml.Element("dictionaryitems")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
DataTypes = xml.Element("datatypes")?.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>(),
|
||||
Files = xml.Element("files")?.Elements("file").Select(x => x.Value).ToList() ?? new List<string>()
|
||||
};
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public XElement ToXml(PackageDefinition def)
|
||||
{
|
||||
var actionsXml = new XElement("actions");
|
||||
try
|
||||
{
|
||||
actionsXml = XElement.Parse(def.Actions);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Warn<PackagesRepository>(e, "Could not add package actions to the package xml definition, the xml did not parse");
|
||||
}
|
||||
|
||||
var packageXml = new XElement("package",
|
||||
new XAttribute("id", def.Id),
|
||||
new XAttribute("version", def.Version ?? string.Empty),
|
||||
new XAttribute("url", def.Url ?? string.Empty),
|
||||
new XAttribute("name", def.Name ?? string.Empty),
|
||||
new XAttribute("packagePath", def.PackagePath ?? string.Empty),
|
||||
new XAttribute("iconUrl", def.IconUrl ?? string.Empty),
|
||||
new XAttribute("umbVersion", def.UmbracoVersion),
|
||||
new XAttribute("packageGuid", def.PackageId),
|
||||
new XAttribute("view", def.PackageView ?? string.Empty),
|
||||
|
||||
new XElement("license",
|
||||
new XCData(def.License ?? string.Empty),
|
||||
new XAttribute("url", def.LicenseUrl ?? string.Empty)),
|
||||
|
||||
new XElement("author",
|
||||
new XCData(def.Author ?? string.Empty),
|
||||
new XAttribute("url", def.AuthorUrl ?? string.Empty)),
|
||||
|
||||
new XElement("contributors", (def.Contributors ?? Array.Empty<string>()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("contributor", x))),
|
||||
|
||||
new XElement("readme", new XCData(def.Readme ?? string.Empty)),
|
||||
actionsXml,
|
||||
new XElement("datatypes", string.Join(",", def.DataTypes ?? Array.Empty<string>())),
|
||||
|
||||
new XElement("content",
|
||||
new XAttribute("nodeId", def.ContentNodeId ?? string.Empty),
|
||||
new XAttribute("loadChildNodes", def.ContentLoadChildNodes)),
|
||||
|
||||
new XElement("templates", string.Join(",", def.Templates ?? Array.Empty<string>())),
|
||||
new XElement("stylesheets", string.Join(",", def.Stylesheets ?? Array.Empty<string>())),
|
||||
new XElement("documentTypes", string.Join(",", def.DocumentTypes ?? Array.Empty<string>())),
|
||||
new XElement("macros", string.Join(",", def.Macros ?? Array.Empty<string>())),
|
||||
new XElement("files", (def.Files ?? Array.Empty<string>()).Where(x => !x.IsNullOrWhiteSpace()).Select(x => new XElement("file", x))),
|
||||
new XElement("languages", string.Join(",", def.Languages ?? Array.Empty<string>())),
|
||||
new XElement("dictionaryitems", string.Join(",", def.DictionaryItems ?? Array.Empty<string>())));
|
||||
|
||||
return packageXml;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Packaging;
|
||||
using Umbraco.Core.Services;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Umbraco.Core.Packaging
|
||||
{
|
||||
/// <summary>
|
||||
/// Installs package files
|
||||
/// </summary>
|
||||
internal class PackageFileInstallation
|
||||
{
|
||||
private readonly CompiledPackageXmlParser _parser;
|
||||
private readonly IIOHelper _ioHelper;
|
||||
private readonly IProfilingLogger _logger;
|
||||
private readonly PackageExtraction _packageExtraction;
|
||||
|
||||
public PackageFileInstallation(CompiledPackageXmlParser parser, IIOHelper ioHelper, IProfilingLogger logger)
|
||||
{
|
||||
_parser = parser;
|
||||
_ioHelper = ioHelper;
|
||||
_logger = logger;
|
||||
_packageExtraction = new PackageExtraction();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of all installed file paths
|
||||
/// </summary>
|
||||
/// <param name="compiledPackage"></param>
|
||||
/// <param name="packageFile"></param>
|
||||
/// <param name="targetRootFolder">
|
||||
/// The absolute path of where to extract the package files (normally the application root)
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<string> InstallFiles(CompiledPackage compiledPackage, FileInfo packageFile, string targetRootFolder)
|
||||
{
|
||||
using (_logger.DebugDuration<PackageFileInstallation>(
|
||||
"Installing package files for package " + compiledPackage.Name,
|
||||
"Package file installation complete for package " + compiledPackage.Name))
|
||||
{
|
||||
var sourceAndRelativeDest = _parser.ExtractSourceDestinationFileInformation(compiledPackage.Files);
|
||||
var sourceAndAbsDest = AppendRootToDestination(targetRootFolder, sourceAndRelativeDest);
|
||||
|
||||
_packageExtraction.CopyFilesFromArchive(packageFile, sourceAndAbsDest);
|
||||
|
||||
return sourceAndRelativeDest.Select(sd => sd.appRelativePath).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> UninstallFiles(PackageDefinition package)
|
||||
{
|
||||
var removedFiles = new List<string>();
|
||||
|
||||
foreach (var item in package.Files.ToArray())
|
||||
{
|
||||
removedFiles.Add(_ioHelper.GetRelativePath(item));
|
||||
|
||||
//here we need to try to find the file in question as most packages does not support the tilde char
|
||||
var file = _ioHelper.FindFile(item);
|
||||
if (file != null)
|
||||
{
|
||||
// TODO: Surely this should be ~/ ?
|
||||
file = file.EnsureStartsWith("/");
|
||||
var filePath = _ioHelper.MapPath(file);
|
||||
|
||||
if (File.Exists(filePath))
|
||||
File.Delete(filePath);
|
||||
|
||||
}
|
||||
package.Files.Remove(file);
|
||||
}
|
||||
|
||||
return removedFiles;
|
||||
}
|
||||
|
||||
private static IEnumerable<(string packageUniqueFile, string appAbsolutePath)> AppendRootToDestination(string applicationRootFolder, IEnumerable<(string packageUniqueFile, string appRelativePath)> sourceDestination)
|
||||
{
|
||||
return
|
||||
sourceDestination.Select(
|
||||
sd => (sd.packageUniqueFile, Path.Combine(applicationRootFolder, sd.appRelativePath))).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user