using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
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
{
///
/// Installs package files
///
internal class PackageFileInstallation
{
private readonly CompiledPackageXmlParser _parser;
private readonly IProfilingLogger _logger;
private readonly PackageExtraction _packageExtraction;
public PackageFileInstallation(CompiledPackageXmlParser parser, IProfilingLogger logger)
{
_parser = parser;
_logger = logger;
_packageExtraction = new PackageExtraction();
}
///
/// Returns a list of all installed file paths
///
///
///
///
/// The absolute path of where to extract the package files (normally the application root)
///
///
public IEnumerable InstallFiles(CompiledPackage compiledPackage, FileInfo packageFile, string targetRootFolder)
{
using (_logger.DebugDuration(
"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 UninstallFiles(PackageDefinition package)
{
var removedFiles = new List();
foreach (var item in package.Files.ToArray())
{
removedFiles.Add(item.GetRelativePath());
//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();
}
}
}