2010-07-18 12:36:02 -07:00
|
|
|
using System;
|
2010-07-22 22:09:34 -07:00
|
|
|
using System.Collections.Generic;
|
2010-07-06 18:56:55 -07:00
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Reflection;
|
|
|
|
using System.Xml.Linq;
|
2010-11-05 18:17:12 -07:00
|
|
|
using NuGet;
|
2010-07-22 22:09:34 -07:00
|
|
|
using Orchard.Environment.Extensions;
|
2010-07-06 18:56:55 -07:00
|
|
|
using Orchard.FileSystems.VirtualPath;
|
2010-07-18 14:29:31 -07:00
|
|
|
using Orchard.Localization;
|
2010-07-06 18:56:55 -07:00
|
|
|
|
2010-11-05 18:17:12 -07:00
|
|
|
using NuGetPackageManager = NuGet.PackageManager;
|
|
|
|
|
2010-07-22 22:09:34 -07:00
|
|
|
namespace Orchard.Packaging.Services {
|
|
|
|
[OrchardFeature("PackagingServices")]
|
2010-07-06 18:56:55 -07:00
|
|
|
public class PackageExpander : IPackageExpander {
|
|
|
|
private const string ContentTypePrefix = "Orchard ";
|
|
|
|
private readonly IVirtualPathProvider _virtualPathProvider;
|
|
|
|
|
2010-07-18 14:29:31 -07:00
|
|
|
public PackageExpander(IVirtualPathProvider virtualPathProvider) {
|
2010-07-06 18:56:55 -07:00
|
|
|
_virtualPathProvider = virtualPathProvider;
|
2010-07-18 14:29:31 -07:00
|
|
|
|
|
|
|
T = NullLocalizer.Instance;
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
|
2010-07-18 14:29:31 -07:00
|
|
|
public Localizer T { get; set; }
|
|
|
|
|
2010-07-06 18:56:55 -07:00
|
|
|
|
2010-11-05 18:17:12 -07:00
|
|
|
public PackageInfo ExpandPackage(string packageId, string version, string location, string destination) {
|
2010-07-06 18:56:55 -07:00
|
|
|
var context = new ExpandContext();
|
2010-11-05 18:17:12 -07:00
|
|
|
|
|
|
|
var packagesPath = Path.Combine(destination, "packages");
|
|
|
|
var projectPath = Path.Combine(destination, "Orchard.Web");
|
|
|
|
|
|
|
|
BeginPackage(context, packageId, version, location, packagesPath);
|
2010-07-06 18:56:55 -07:00
|
|
|
try {
|
2010-11-05 18:17:12 -07:00
|
|
|
|
|
|
|
var packageRepository = Uri.IsWellFormedUriString(location, UriKind.Absolute)
|
|
|
|
? new DataServicePackageRepository(new Uri(location))
|
|
|
|
: new LocalPackageRepository(location) as IPackageRepository;
|
|
|
|
|
|
|
|
var package = packageRepository.FindPackage(packageId, exactVersion: new Version(version));
|
|
|
|
|
|
|
|
if(package == null) {
|
|
|
|
throw new ArgumentException(T("The specified package could not be found: {0}.{1}", packageId, version).Text);
|
|
|
|
}
|
|
|
|
|
|
|
|
context.ExtensionName = package.Title;
|
|
|
|
context.ExtensionVersion = package.Version.ToString();
|
|
|
|
context.TargetPath = projectPath;
|
|
|
|
|
|
|
|
// packageManager.InstallPackage(package, ignoreDependencies: true);
|
|
|
|
|
|
|
|
//var packageManager = new NuGetPackageManager(
|
|
|
|
// packageRepository,
|
|
|
|
// new DefaultPackagePathResolver(location),
|
|
|
|
// new FileBasedProjectSystem(packagesPath)
|
|
|
|
//);
|
|
|
|
|
|
|
|
var projectManager = new ProjectManager(
|
|
|
|
packageRepository, // source repository for the package to install
|
|
|
|
new DefaultPackagePathResolver(location),
|
|
|
|
new FileBasedProjectSystem(projectPath), // the location of the project (where to copy the content files)
|
|
|
|
new LocalPackageRepository(packagesPath) // the location of the uncompressed package, used to check if the package is already installed
|
|
|
|
);
|
|
|
|
|
|
|
|
// add the package to the project
|
|
|
|
projectManager.AddPackageReference(packageId, new Version(version));
|
|
|
|
|
|
|
|
|
|
|
|
#if REFACTORING
|
2010-07-06 18:56:55 -07:00
|
|
|
GetCoreProperties(context);
|
|
|
|
EstablishPaths(context, _virtualPathProvider);
|
|
|
|
|
2010-07-22 22:09:34 -07:00
|
|
|
string projectFile = context.ExtensionName + ".csproj";
|
2010-07-06 18:56:55 -07:00
|
|
|
if (LoadProject(context, projectFile)) {
|
|
|
|
ExtractFile(context, projectFile);
|
|
|
|
ExtractProjectFiles(context, "Compile", "Content", "None", "EmbeddedResource");
|
|
|
|
ExtractReferenceFiles(context);
|
|
|
|
}
|
2010-10-04 14:52:46 -07:00
|
|
|
else if (context.ExtensionType == "Theme") {
|
|
|
|
// this is a simple theme with no csproj
|
|
|
|
ExtractThemeFiles(context);
|
|
|
|
}
|
2010-11-05 18:17:12 -07:00
|
|
|
#endif
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
finally {
|
|
|
|
EndPackage(context);
|
|
|
|
}
|
2010-07-18 13:09:45 -07:00
|
|
|
|
|
|
|
return new PackageInfo {
|
|
|
|
ExtensionName = context.ExtensionName,
|
|
|
|
ExtensionVersion = context.ExtensionVersion,
|
|
|
|
ExtensionType = context.ExtensionType,
|
|
|
|
ExtensionPath = context.TargetPath
|
|
|
|
};
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private void ExtractFile(ExpandContext context, string relativePath) {
|
2010-10-27 11:19:17 -07:00
|
|
|
#if REFACTORING
|
2010-07-22 22:09:34 -07:00
|
|
|
Uri partUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
|
|
|
|
PackagePart packagePart = context.Package.GetPart(partUri);
|
|
|
|
using (Stream packageStream = packagePart.GetStream(FileMode.Open, FileAccess.Read)) {
|
|
|
|
string filePath = _virtualPathProvider.Combine(context.TargetPath, relativePath);
|
|
|
|
string folderPath = _virtualPathProvider.GetDirectoryName(filePath);
|
|
|
|
if (!_virtualPathProvider.DirectoryExists(folderPath)) {
|
2010-07-18 14:29:31 -07:00
|
|
|
_virtualPathProvider.CreateDirectory(folderPath);
|
2010-07-22 22:09:34 -07:00
|
|
|
}
|
2010-07-06 18:56:55 -07:00
|
|
|
|
2010-07-22 22:09:34 -07:00
|
|
|
using (Stream fileStream = _virtualPathProvider.CreateFile(filePath)) {
|
2010-07-06 18:56:55 -07:00
|
|
|
packageStream.CopyTo(fileStream);
|
|
|
|
}
|
|
|
|
}
|
2010-10-27 11:19:17 -07:00
|
|
|
#endif
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private void ExtractProjectFiles(ExpandContext context, params string[] itemGroupTypes) {
|
2010-07-22 22:09:34 -07:00
|
|
|
IEnumerable<XElement> itemGroups = context.Project
|
2010-07-06 18:56:55 -07:00
|
|
|
.Elements(Ns("Project"))
|
|
|
|
.Elements(Ns("ItemGroup"));
|
|
|
|
|
2010-07-22 22:09:34 -07:00
|
|
|
foreach (string itemGroupType in itemGroupTypes) {
|
|
|
|
IEnumerable<string> includePaths = itemGroups
|
2010-07-06 18:56:55 -07:00
|
|
|
.Elements(Ns(itemGroupType))
|
|
|
|
.Attributes("Include")
|
|
|
|
.Select(x => x.Value);
|
2010-07-22 22:09:34 -07:00
|
|
|
foreach (string includePath in includePaths) {
|
2010-07-06 18:56:55 -07:00
|
|
|
ExtractFile(context, includePath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ExtractReferenceFiles(ExpandContext context) {
|
|
|
|
var entries = context.Project
|
|
|
|
.Elements(Ns("Project"))
|
|
|
|
.Elements(Ns("ItemGroup"))
|
|
|
|
.Elements(Ns("Reference"))
|
|
|
|
.Select(reference => new {
|
|
|
|
Include = reference.Attribute("Include"),
|
|
|
|
HintPath = reference.Element(Ns("HintPath"))
|
|
|
|
})
|
|
|
|
.Where(entry => entry.Include != null);
|
|
|
|
|
|
|
|
foreach (var entry in entries) {
|
|
|
|
var assemblyName = new AssemblyName(entry.Include.Value);
|
2010-07-22 22:09:34 -07:00
|
|
|
string hintPath = entry.HintPath != null ? entry.HintPath.Value : null;
|
2010-07-06 18:56:55 -07:00
|
|
|
|
2010-07-22 22:09:34 -07:00
|
|
|
string virtualPath = "bin/" + assemblyName.Name + ".dll";
|
2010-07-06 18:56:55 -07:00
|
|
|
if (PartExists(context, virtualPath)) {
|
|
|
|
ExtractFile(context, virtualPath);
|
|
|
|
}
|
2010-07-22 22:09:34 -07:00
|
|
|
else if (hintPath != null) {}
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-04 14:52:46 -07:00
|
|
|
private void ExtractThemeFiles(ExpandContext context) {
|
2010-10-27 11:19:17 -07:00
|
|
|
#if REFACTORING
|
2010-10-04 14:52:46 -07:00
|
|
|
foreach (var relativePath in from p in context.Package.GetParts()
|
|
|
|
where p.Uri.ToString().StartsWith("/" + context.ExtensionName + "/", StringComparison.OrdinalIgnoreCase)
|
|
|
|
select p.Uri.ToString().Substring(("/" + context.ExtensionName + "/").Length)) {
|
|
|
|
ExtractFile(context, relativePath);
|
|
|
|
}
|
2010-10-27 11:19:17 -07:00
|
|
|
#endif
|
2010-10-04 14:52:46 -07:00
|
|
|
}
|
|
|
|
|
2010-07-06 18:56:55 -07:00
|
|
|
private bool PartExists(ExpandContext context, string relativePath) {
|
2010-10-27 11:19:17 -07:00
|
|
|
#if REFACTORING
|
2010-07-22 22:09:34 -07:00
|
|
|
Uri projectUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
|
2010-07-06 18:56:55 -07:00
|
|
|
return context.Package.PartExists(projectUri);
|
2010-10-27 11:19:17 -07:00
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private XName Ns(string localName) {
|
|
|
|
return XName.Get(localName, "http://schemas.microsoft.com/developer/msbuild/2003");
|
|
|
|
}
|
2010-07-22 22:09:34 -07:00
|
|
|
|
2010-07-06 18:56:55 -07:00
|
|
|
private static bool LoadProject(ExpandContext context, string relativePath) {
|
2010-10-27 11:19:17 -07:00
|
|
|
#if REFACTORING
|
2010-07-22 22:09:34 -07:00
|
|
|
Uri projectUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
|
|
|
|
if (!context.Package.PartExists(projectUri)) {
|
2010-07-06 18:56:55 -07:00
|
|
|
return false;
|
2010-07-22 22:09:34 -07:00
|
|
|
}
|
|
|
|
PackagePart part = context.Package.GetPart(projectUri);
|
|
|
|
using (Stream stream = part.GetStream(FileMode.Open, FileAccess.Read)) {
|
2010-07-06 18:56:55 -07:00
|
|
|
context.Project = XDocument.Load(stream);
|
|
|
|
}
|
2010-10-27 11:19:17 -07:00
|
|
|
#endif
|
2010-07-06 18:56:55 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-11-05 18:17:12 -07:00
|
|
|
private void BeginPackage(ExpandContext context, string packageId, string version, string location, string destination) {
|
|
|
|
|
2010-10-27 11:19:17 -07:00
|
|
|
#if REFACTORING
|
2010-07-06 18:56:55 -07:00
|
|
|
context.Package = Package.Open(context.Stream, FileMode.Open, FileAccess.Read);
|
2010-10-27 11:19:17 -07:00
|
|
|
#endif
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private void EndPackage(ExpandContext context) {
|
2010-10-27 11:19:17 -07:00
|
|
|
#if REFACTORING
|
2010-07-06 18:56:55 -07:00
|
|
|
context.Package.Close();
|
2010-10-27 11:19:17 -07:00
|
|
|
#endif
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private void GetCoreProperties(ExpandContext context) {
|
2010-10-27 11:19:17 -07:00
|
|
|
#if REFACTORING
|
2010-07-06 18:56:55 -07:00
|
|
|
context.ExtensionName = context.Package.PackageProperties.Identifier;
|
2010-07-18 13:09:45 -07:00
|
|
|
context.ExtensionVersion = context.Package.PackageProperties.Version;
|
2010-07-06 18:56:55 -07:00
|
|
|
|
2010-07-22 22:09:34 -07:00
|
|
|
string contentType = context.Package.PackageProperties.ContentType;
|
|
|
|
if (contentType.StartsWith(ContentTypePrefix)) {
|
2010-07-06 18:56:55 -07:00
|
|
|
context.ExtensionType = contentType.Substring(ContentTypePrefix.Length);
|
2010-07-22 22:09:34 -07:00
|
|
|
}
|
2010-10-27 11:19:17 -07:00
|
|
|
#endif
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private void EstablishPaths(ExpandContext context, IVirtualPathProvider virtualPathProvider) {
|
|
|
|
context.SourcePath = "\\" + context.ExtensionName + "\\";
|
2010-07-18 14:29:31 -07:00
|
|
|
switch (context.ExtensionType) {
|
|
|
|
case "Theme":
|
|
|
|
context.TargetPath = virtualPathProvider.Combine("~/Themes/" + context.ExtensionName);
|
|
|
|
break;
|
|
|
|
case "Module":
|
|
|
|
context.TargetPath = virtualPathProvider.Combine("~/Modules/" + context.ExtensionName);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new OrchardCoreException(T("Unknown extension type \"{0}\"", context.ExtensionType));
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
}
|
2010-07-22 22:09:34 -07:00
|
|
|
|
|
|
|
#region Nested type: ExpandContext
|
|
|
|
|
|
|
|
private class ExpandContext {
|
|
|
|
public Stream Stream { get; set; }
|
2010-10-27 11:19:17 -07:00
|
|
|
//public Package Package { get; set; }
|
2010-07-22 22:09:34 -07:00
|
|
|
|
|
|
|
public string ExtensionName { get; set; }
|
|
|
|
public string ExtensionVersion { get; set; }
|
|
|
|
public string ExtensionType { get; set; }
|
|
|
|
|
|
|
|
public string TargetPath { get; set; }
|
|
|
|
|
|
|
|
public string SourcePath { get; set; }
|
|
|
|
|
|
|
|
public XDocument Project { get; set; }
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
2010-07-06 18:56:55 -07:00
|
|
|
}
|
|
|
|
}
|