From 14101b18438c29f3d5ef5a22a3864efd489600fb Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Mon, 4 Oct 2010 14:52:46 -0700 Subject: [PATCH 1/4] Ability to create and install packages of simple themes. --HG-- branch : dev --- src/Orchard.Tests/Stubs/StubWebSiteFolder.cs | 4 ++ .../Commands/PackagingCommands.cs | 2 +- .../Services/PackageBuilder.cs | 45 +++++++++++++++++-- .../Services/PackageExpander.cs | 12 +++++ .../FileSystems/WebSite/IWebSiteFolder.cs | 1 + .../FileSystems/WebSite/WebSiteFolder.cs | 30 +++++++++++++ 6 files changed, 90 insertions(+), 4 deletions(-) diff --git a/src/Orchard.Tests/Stubs/StubWebSiteFolder.cs b/src/Orchard.Tests/Stubs/StubWebSiteFolder.cs index 8afadb142..ecfb7bfda 100644 --- a/src/Orchard.Tests/Stubs/StubWebSiteFolder.cs +++ b/src/Orchard.Tests/Stubs/StubWebSiteFolder.cs @@ -14,6 +14,10 @@ namespace Orchard.Tests.Stubs { return Directory.GetDirectories(path); } + public IEnumerable ListFiles(string path, bool recursive) { + throw new NotImplementedException(); + } + public bool FileExists(string virtualPath) { throw new NotImplementedException(); } diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Commands/PackagingCommands.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Commands/PackagingCommands.cs index e98dc6496..e7720ff51 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Commands/PackagingCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Commands/PackagingCommands.cs @@ -38,7 +38,7 @@ namespace Orchard.Packaging.Commands { } [CommandHelp("package install \r\n\t" + "Install a module from a package .")] - [CommandName("package install ")] + [CommandName("package install")] public void InstallPackage(string filename) { if (!File.Exists(filename)) { Context.Output.WriteLine(T("File \"{0}\" does not exist.", filename)); diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageBuilder.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageBuilder.cs index 64fb2499c..0ed3cbcb3 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageBuilder.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageBuilder.cs @@ -5,6 +5,8 @@ using System.IO.Packaging; using System.Linq; using System.Net.Mime; using System.Reflection; +using System.Web; +using System.Web.Hosting; using System.Xml.Linq; using Orchard.Environment.Extensions; using Orchard.Environment.Extensions.Models; @@ -16,6 +18,19 @@ namespace Orchard.Packaging.Services { private readonly IExtensionManager _extensionManager; private readonly IWebSiteFolder _webSiteFolder; + private static readonly string[] _ignoredThemeExtensions = new[] { + "obj", "pdb", "exclude" + }; + private static readonly string[] _ignoredThemePaths = new[] { + "/obj/" + }; + + private static bool IgnoreFile(string filePath) { + return String.IsNullOrEmpty(filePath) || + _ignoredThemePaths.Any(filePath.Contains) || + _ignoredThemeExtensions.Contains(Path.GetExtension(filePath) ?? ""); + } + public PackageBuilder(IExtensionManager extensionManager, IWebSiteFolder webSiteFolder) { _extensionManager = extensionManager; _webSiteFolder = webSiteFolder; @@ -27,7 +42,7 @@ namespace Orchard.Packaging.Services { var context = new CreateContext(); BeginPackage(context); try { - EstablishPaths(context, _webSiteFolder, extensionDescriptor.Location, extensionDescriptor.Name); + EstablishPaths(context, _webSiteFolder, extensionDescriptor.Location, extensionDescriptor.Name, extensionDescriptor.ExtensionType); SetCoreProperties(context, extensionDescriptor); string projectFile = extensionDescriptor.Name + ".csproj"; @@ -36,6 +51,10 @@ namespace Orchard.Packaging.Services { EmbedProjectFiles(context, "Compile", "Content", "None", "EmbeddedResource"); EmbedReferenceFiles(context); } + else if (extensionDescriptor.ExtensionType == "Theme") { + // this is a simple theme with no csproj + EmbedThemeFiles(context); + } } finally { EndPackage(context); @@ -110,6 +129,21 @@ namespace Orchard.Packaging.Services { } } + private void EmbedThemeFiles(CreateContext context) { + var basePath = HostingEnvironment.VirtualPathProvider.GetDirectory(context.SourcePath).VirtualPath; + foreach (var virtualPath in context.SourceFolder.ListFiles(context.SourcePath, true)) { + // ignore dlls, etc + if (IgnoreFile(virtualPath)) { + continue; + } + // full virtual path given but we need the relative path so it can be put into + // the package that way (the package itself is the logical base path). + // Get it by stripping the basePath off including the slash. + var relativePath = virtualPath.Replace(basePath, ""); + EmbedVirtualFile(context, relativePath, MediaTypeNames.Application.Octet); + } + } + private XName Ns(string localName) { return XName.Get(localName, "http://schemas.microsoft.com/developer/msbuild/2003"); } @@ -120,9 +154,14 @@ namespace Orchard.Packaging.Services { context.Package = Package.Open(context.Stream, FileMode.Create, FileAccess.ReadWrite); } - private static void EstablishPaths(CreateContext context, IWebSiteFolder webSiteFolder, string locationPath, string moduleName) { + private static void EstablishPaths(CreateContext context, IWebSiteFolder webSiteFolder, string locationPath, string moduleName, string moduleType) { context.SourceFolder = webSiteFolder; - context.SourcePath = "~/Modules/" + moduleName + "/"; + if (moduleType == "Theme") { + context.SourcePath = "~/Themes/" + moduleName + "/"; + } + else { + context.SourcePath = "~/Modules/" + moduleName + "/"; + } context.TargetPath = "\\" + moduleName + "\\"; } diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageExpander.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageExpander.cs index e794a4627..c5fee8195 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageExpander.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageExpander.cs @@ -38,6 +38,10 @@ namespace Orchard.Packaging.Services { ExtractProjectFiles(context, "Compile", "Content", "None", "EmbeddedResource"); ExtractReferenceFiles(context); } + else if (context.ExtensionType == "Theme") { + // this is a simple theme with no csproj + ExtractThemeFiles(context); + } } finally { EndPackage(context); @@ -108,6 +112,14 @@ namespace Orchard.Packaging.Services { } } + private void ExtractThemeFiles(ExpandContext context) { + 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); + } + } + private bool PartExists(ExpandContext context, string relativePath) { Uri projectUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative)); return context.Package.PartExists(projectUri); diff --git a/src/Orchard/FileSystems/WebSite/IWebSiteFolder.cs b/src/Orchard/FileSystems/WebSite/IWebSiteFolder.cs index 87aa3d358..c03ebd9c6 100644 --- a/src/Orchard/FileSystems/WebSite/IWebSiteFolder.cs +++ b/src/Orchard/FileSystems/WebSite/IWebSiteFolder.cs @@ -8,6 +8,7 @@ namespace Orchard.FileSystems.WebSite { /// public interface IWebSiteFolder : IVolatileProvider { IEnumerable ListDirectories(string virtualPath); + IEnumerable ListFiles(string virtualPath, bool recursive); bool FileExists(string virtualPath); string ReadFile(string virtualPath); diff --git a/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs b/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs index 0fbf0e1ad..7a1af6ac9 100644 --- a/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs +++ b/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs @@ -27,6 +27,36 @@ namespace Orchard.FileSystems.WebSite { .Select(d => d.VirtualPath) .ToArray(); } + + private IEnumerable ListFiles(IEnumerable directories) { + return from dir in directories + from file in ListFiles(dir, true) + select file; + } + + public IEnumerable ListFiles(string virtualPath, bool recursive) { + if (!recursive) { + return from VirtualFile file in HostingEnvironment.VirtualPathProvider.GetDirectory(virtualPath).Files + select file.VirtualPath; + } + return (from VirtualFile file in HostingEnvironment.VirtualPathProvider.GetDirectory(virtualPath).Files + select file.VirtualPath).Concat(ListFiles(ListDirectories(virtualPath))); +/* + + var path = HostingEnvironment.MapPath(virtualPath); + if (path == null || !Directory.Exists(path)) { + return Enumerable.Empty(); + } + + if (!path.EndsWith("\\")) { + path += "\\"; + } + + var files = Directory.GetFiles(path, searchPattern, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); + // strip base path to make it relative and replace '\' with '/' + return from file in files + select "~/" + file.Replace(path, "").Replace("\\", "/");*/ + } public bool FileExists(string virtualPath) { return HostingEnvironment.VirtualPathProvider.FileExists(virtualPath); From d8266701d5b4f705760d7446a41e2bfbe04abeff Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Mon, 4 Oct 2010 14:56:59 -0700 Subject: [PATCH 2/4] Remove commented code --HG-- branch : dev --- src/Orchard/FileSystems/WebSite/WebSiteFolder.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs b/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs index 7a1af6ac9..2b4d87f92 100644 --- a/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs +++ b/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs @@ -41,21 +41,6 @@ namespace Orchard.FileSystems.WebSite { } return (from VirtualFile file in HostingEnvironment.VirtualPathProvider.GetDirectory(virtualPath).Files select file.VirtualPath).Concat(ListFiles(ListDirectories(virtualPath))); -/* - - var path = HostingEnvironment.MapPath(virtualPath); - if (path == null || !Directory.Exists(path)) { - return Enumerable.Empty(); - } - - if (!path.EndsWith("\\")) { - path += "\\"; - } - - var files = Directory.GetFiles(path, searchPattern, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); - // strip base path to make it relative and replace '\' with '/' - return from file in files - select "~/" + file.Replace(path, "").Replace("\\", "/");*/ } public bool FileExists(string virtualPath) { From d142f8f93b12bdf2191b6bdc5a5cdb98f067146d Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Tue, 5 Oct 2010 11:20:30 -0700 Subject: [PATCH 3/4] generate: dont ignore dlls when copying a theme --HG-- branch : dev --- .../Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs index e75881aab..fd688e1a8 100644 --- a/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.CodeGeneration/Commands/CodeGenerationCommands.cs @@ -20,10 +20,10 @@ namespace Orchard.CodeGeneration.Commands { private readonly ISchemaCommandGenerator _schemaCommandGenerator; private static readonly string[] _ignoredExtensions = new [] { - "dll", "obj", "pdb", "exclude" + "obj", "pdb", "exclude" }; private static readonly string[] _ignoredPaths = new [] { - "/bin/", "/obj/" + "/obj/" }; private static readonly string[] _themeDirectories = new [] { "", "Content", "Styles", "Scripts", "Views", "Zones" From 53dbd7c30d19db028e091886894231c632985d52 Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Tue, 5 Oct 2010 11:39:31 -0700 Subject: [PATCH 4/4] Code review improvements. Fix base path resolution. --HG-- branch : dev --- .../Services/PackageBuilder.cs | 2 +- .../FileSystems/WebSite/WebSiteFolder.cs | 31 ++++++++----------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageBuilder.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageBuilder.cs index 0ed3cbcb3..d4c478196 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageBuilder.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageBuilder.cs @@ -130,7 +130,7 @@ namespace Orchard.Packaging.Services { } private void EmbedThemeFiles(CreateContext context) { - var basePath = HostingEnvironment.VirtualPathProvider.GetDirectory(context.SourcePath).VirtualPath; + var basePath = context.SourcePath; foreach (var virtualPath in context.SourceFolder.ListFiles(context.SourcePath, true)) { // ignore dlls, etc if (IgnoreFile(virtualPath)) { diff --git a/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs b/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs index 2b4d87f92..437438f6b 100644 --- a/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs +++ b/src/Orchard/FileSystems/WebSite/WebSiteFolder.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Web.Hosting; using Orchard.Caching; -using Orchard.Environment; using Orchard.FileSystems.VirtualPath; namespace Orchard.FileSystems.WebSite { @@ -18,33 +17,26 @@ namespace Orchard.FileSystems.WebSite { } public IEnumerable ListDirectories(string virtualPath) { - if (!HostingEnvironment.VirtualPathProvider.DirectoryExists(virtualPath)) + if (!_virtualPathProvider.DirectoryExists(virtualPath)) { return Enumerable.Empty(); + } - return HostingEnvironment.VirtualPathProvider - .GetDirectory(virtualPath) - .Directories.OfType() - .Select(d => d.VirtualPath) - .ToArray(); + return _virtualPathProvider.ListDirectories(virtualPath); } private IEnumerable ListFiles(IEnumerable directories) { - return from dir in directories - from file in ListFiles(dir, true) - select file; + return directories.SelectMany(d => ListFiles(d, true)); } public IEnumerable ListFiles(string virtualPath, bool recursive) { if (!recursive) { - return from VirtualFile file in HostingEnvironment.VirtualPathProvider.GetDirectory(virtualPath).Files - select file.VirtualPath; + return _virtualPathProvider.ListFiles(virtualPath); } - return (from VirtualFile file in HostingEnvironment.VirtualPathProvider.GetDirectory(virtualPath).Files - select file.VirtualPath).Concat(ListFiles(ListDirectories(virtualPath))); + return _virtualPathProvider.ListFiles(virtualPath).Concat(ListFiles(ListDirectories(virtualPath))); } public bool FileExists(string virtualPath) { - return HostingEnvironment.VirtualPathProvider.FileExists(virtualPath); + return _virtualPathProvider.FileExists(virtualPath); } public string ReadFile(string virtualPath) { @@ -52,8 +44,9 @@ namespace Orchard.FileSystems.WebSite { } public string ReadFile(string virtualPath, bool actualContent) { - if (!HostingEnvironment.VirtualPathProvider.FileExists(virtualPath)) + if (!_virtualPathProvider.FileExists(virtualPath)) { return null; + } if (actualContent) { var physicalPath = _virtualPathProvider.MapPath(virtualPath); @@ -64,7 +57,7 @@ namespace Orchard.FileSystems.WebSite { } } else { - using (var stream = VirtualPathProvider.OpenFile(Normalize(virtualPath))) { + using (var stream = _virtualPathProvider.OpenFile(Normalize(virtualPath))) { using (var reader = new StreamReader(stream)) { return reader.ReadToEnd(); } @@ -89,7 +82,7 @@ namespace Orchard.FileSystems.WebSite { } } else { - using (var stream = VirtualPathProvider.OpenFile(Normalize(virtualPath))) { + using (var stream = _virtualPathProvider.OpenFile(Normalize(virtualPath))) { stream.CopyTo(destination); } } @@ -100,6 +93,8 @@ namespace Orchard.FileSystems.WebSite { } static string Normalize(string virtualPath) { + // todo: use IVirtualPathProvider instance instead of static. + // Currently IVirtualPathProvider has no way of doing normalization like this return HostingEnvironment.VirtualPathProvider.GetFile(virtualPath).VirtualPath; } }