Dynamic compilation bug fix

Symptom: One the first modification to a source file starts a dynamic
compilation. After that, changes are ignored.

Fix: The problem was that we need to override the "FileHash" value returned
for csproj files to include the hash of all source files. This is so that
any changes to any source file will notify ASP.NET that the .csproj file
needs to be recompiled using a the corresponding build provider.

--HG--
branch : dev
This commit is contained in:
Renaud Paquay
2010-07-15 17:30:07 -07:00
parent fe35cc634a
commit baebaec05d
8 changed files with 123 additions and 0 deletions

View File

@@ -108,6 +108,10 @@ namespace Orchard.Tests.Environment.Extensions {
throw new NotImplementedException();
}
public IEnumerable<string> GetFileDependencies(DependencyDescriptor dependency, string virtualPath) {
throw new NotImplementedException();
}
#endregion
}

View File

@@ -108,6 +108,10 @@ namespace Orchard.Tests.Environment.Extensions {
throw new NotImplementedException();
}
public IEnumerable<string> GetFileDependencies(DependencyDescriptor dependency, string virtualPath) {
throw new NotImplementedException();
}
#endregion
}

View File

@@ -47,6 +47,16 @@ namespace Orchard.Environment.Extensions.Loaders {
return GetDependencies(dependency.VirtualPath);
}
public override IEnumerable<string> GetFileDependencies(DependencyDescriptor dependency, string virtualPath){
var path1 = virtualPath.StartsWith("~") ? virtualPath : "~" + virtualPath;
var path2 = dependency.VirtualPath.StartsWith("~") ? dependency.VirtualPath : "~" + dependency.VirtualPath;
if (StringComparer.OrdinalIgnoreCase.Equals(path1, path2)) {
return GetSourceFiles(virtualPath);
}
return base.GetFileDependencies(dependency, virtualPath);
}
public override void Monitor(ExtensionDescriptor descriptor, Action<IVolatileToken> monitor) {
// Monitor .csproj and all .cs files
string projectPath = GetProjectPath(descriptor);

View File

@@ -57,5 +57,9 @@ namespace Orchard.Environment.Extensions.Loaders {
public virtual IEnumerable<string> GetWebFormVirtualDependencies(DependencyDescriptor dependency) {
return Enumerable.Empty<string>();
}
public virtual IEnumerable<string> GetFileDependencies(DependencyDescriptor dependency, string virtualPath) {
return Enumerable.Empty<string>();
}
}
}

View File

@@ -42,5 +42,6 @@ namespace Orchard.Environment.Extensions.Loaders {
string GetWebFormAssemblyDirective(DependencyDescriptor dependency);
IEnumerable<string> GetWebFormVirtualDependencies(DependencyDescriptor dependency);
IEnumerable<string> GetFileDependencies(DependencyDescriptor dependency, string virtualPath);
}
}

View File

@@ -38,6 +38,7 @@ namespace Orchard.Environment {
builder.RegisterType<DefaultHostEnvironment>().As<IHostEnvironment>().SingleInstance();
builder.RegisterType<DefaultBuildManager>().As<IBuildManager>().SingleInstance();
builder.RegisterType<WebFormVirtualPathProvider>().As<ICustomVirtualPathProvider>().SingleInstance();
builder.RegisterType<DynamicModuleVirtualPathProvider>().As<ICustomVirtualPathProvider>().SingleInstance();
builder.RegisterType<AppDataFolderRoot>().As<IAppDataFolderRoot>().SingleInstance();
builder.RegisterType<DefaultExtensionCompiler>().As<IExtensionCompiler>().SingleInstance();
builder.RegisterType<DefaultProjectFileParser>().As<IProjectFileParser>().SingleInstance();

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.Hosting;
using Orchard.Environment.Extensions.Loaders;
using Orchard.FileSystems.VirtualPath;
using Orchard.Logging;
namespace Orchard.FileSystems.Dependencies {
public class DynamicModuleVirtualPathProvider : VirtualPathProvider, ICustomVirtualPathProvider {
private readonly IDependenciesFolder _dependenciesFolder;
private readonly IEnumerable<IExtensionLoader> _loaders;
private readonly string[] _modulesPrefixes = { "~/Modules/", "/Modules/" };
public DynamicModuleVirtualPathProvider(IDependenciesFolder dependenciesFolder, IEnumerable<IExtensionLoader> loaders) {
_dependenciesFolder = dependenciesFolder;
_loaders = loaders;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public override bool DirectoryExists(string virtualDir) {
return Previous.DirectoryExists(virtualDir);
}
public override bool FileExists(string virtualPath) {
return Previous.FileExists(virtualPath);
}
public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) {
var result = GetFileHashWorker(virtualPath, virtualPathDependencies);
//Logger.Information("GetFileHash(\"{0}\"): {1}", virtualPath, result);
return result;
}
private string GetFileHashWorker(string virtualPath, IEnumerable virtualPathDependencies) {
var desc = GetDependencyDescriptor(virtualPath);
if (desc != null) {
var loader = _loaders.Where(l => l.Name == desc.LoaderName).FirstOrDefault();
if (loader != null) {
var otherDependencies = loader.GetFileDependencies(desc, virtualPath);
if (otherDependencies.Any()) {
var allDependencies = virtualPathDependencies.OfType<string>().Concat(otherDependencies);
if (Logger.IsEnabled(LogLevel.Debug)) {
Logger.Debug("GetFileHash(\"{0}\") - virtual path dependencies:", virtualPath);
foreach (var dependency in allDependencies) {
Logger.Debug(" Dependency: \"{0}\"", dependency);
}
}
return base.GetFileHash(virtualPath, allDependencies);
}
}
}
return base.GetFileHash(virtualPath, virtualPathDependencies);
}
public override VirtualFile GetFile(string virtualPath) {
return Previous.GetFile(virtualPath);
}
private DependencyDescriptor GetDependencyDescriptor(string virtualPath) {
var prefix = PrefixMatch(virtualPath, _modulesPrefixes);
if (prefix == null)
return null;
var moduleName = ModuleMatch(virtualPath, prefix);
if (moduleName == null)
return null;
return _dependenciesFolder.GetDescriptor(moduleName);
}
private string ModuleMatch(string virtualPath, string prefix) {
var index = virtualPath.IndexOf('/', prefix.Length, virtualPath.Length - prefix.Length);
if (index < 0)
return null;
var moduleName = virtualPath.Substring(prefix.Length, index - prefix.Length);
return (string.IsNullOrEmpty(moduleName) ? null : moduleName);
}
private string PrefixMatch(string virtualPath, params string[] prefixes) {
return prefixes
.FirstOrDefault(p => virtualPath.StartsWith(p, StringComparison.OrdinalIgnoreCase));
}
VirtualPathProvider ICustomVirtualPathProvider.Instance {
get { return this; }
}
}
}

View File

@@ -360,6 +360,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="ContentManagement\DataMigrations\FrameworkDataMigration.cs" />
<Compile Include="FileSystems\Dependencies\DynamicModuleVirtualPathProvider.cs" />
<Compile Include="Utility\Hash.cs" />
<Compile Include="Data\ISessionConfigurationCache.cs" />
<Compile Include="Data\Migration\Generator\ISchemaCommandGenerator.cs" />