Some cleanup around FileProviderRazorProject with tests
This commit is contained in:
parent
1d6b02c1f5
commit
2c6ba372c1
|
|
@ -37,15 +37,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
path = NormalizeAndEnsureValidPath(path);
|
||||
var fileInfo = _provider.GetFileInfo(path);
|
||||
|
||||
string relativePhysicalPath = null;
|
||||
if (fileInfo != null && fileInfo.Exists)
|
||||
{
|
||||
var absoluteBasePath = _hostingEnvironment.ContentRootPath;
|
||||
relativePhysicalPath = fileInfo?.PhysicalPath?.Substring(absoluteBasePath.Length + 1); // Include leading separator
|
||||
relativePhysicalPath = relativePhysicalPath ?? path; // Use the incoming path if the file is not directly accessible
|
||||
}
|
||||
|
||||
return new FileProviderRazorProjectItem(fileInfo, basePath: string.Empty, filePath: path, relativePhysicalPath: relativePhysicalPath);
|
||||
return new FileProviderRazorProjectItem(fileInfo, basePath: string.Empty, filePath: path, root: _hostingEnvironment.ContentRootPath);
|
||||
}
|
||||
|
||||
public override IEnumerable<RazorProjectItem> EnumerateItems(string path)
|
||||
|
|
@ -58,11 +50,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
{
|
||||
if (directory.Exists)
|
||||
{
|
||||
foreach (var file in directory)
|
||||
foreach (var fileInfo in directory)
|
||||
{
|
||||
if (file.IsDirectory)
|
||||
if (fileInfo.IsDirectory)
|
||||
{
|
||||
var relativePath = prefix + "/" + file.Name;
|
||||
var relativePath = prefix + "/" + fileInfo.Name;
|
||||
var subDirectory = _provider.GetDirectoryContents(JoinPath(basePath, relativePath));
|
||||
var children = EnumerateFiles(subDirectory, basePath, relativePath);
|
||||
foreach (var child in children)
|
||||
|
|
@ -70,14 +62,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
yield return child;
|
||||
}
|
||||
}
|
||||
else if (string.Equals(RazorFileExtension, Path.GetExtension(file.Name), StringComparison.OrdinalIgnoreCase))
|
||||
else if (string.Equals(RazorFileExtension, Path.GetExtension(fileInfo.Name), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var filePath = prefix + "/" + file.Name;
|
||||
var absoluteBasePath = _hostingEnvironment.ContentRootPath;
|
||||
var relativePhysicalPath = file.PhysicalPath?.Substring(absoluteBasePath.Length + 1); // Include leading separator
|
||||
relativePhysicalPath = relativePhysicalPath ?? filePath; // Use the incoming path if the file is not directly accessible
|
||||
var filePath = prefix + "/" + fileInfo.Name;
|
||||
|
||||
yield return new FileProviderRazorProjectItem(file, basePath, filePath: filePath, relativePhysicalPath: relativePhysicalPath);
|
||||
yield return new FileProviderRazorProjectItem(fileInfo, basePath, filePath: filePath, root: _hostingEnvironment.ContentRootPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
|
|
@ -9,12 +10,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
{
|
||||
public class FileProviderRazorProjectItem : RazorProjectItem
|
||||
{
|
||||
public FileProviderRazorProjectItem(IFileInfo fileInfo, string basePath, string filePath, string relativePhysicalPath)
|
||||
private string _root;
|
||||
private string _relativePhysicalPath;
|
||||
private bool _isRelativePhysicalPathSet;
|
||||
|
||||
public FileProviderRazorProjectItem(IFileInfo fileInfo, string basePath, string filePath, string root)
|
||||
{
|
||||
FileInfo = fileInfo;
|
||||
BasePath = basePath;
|
||||
FilePath = filePath;
|
||||
RelativePhysicalPath = relativePhysicalPath;
|
||||
_root = root;
|
||||
}
|
||||
|
||||
public IFileInfo FileInfo { get; }
|
||||
|
|
@ -27,7 +32,30 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
|
||||
public override string PhysicalPath => FileInfo.PhysicalPath;
|
||||
|
||||
public override string RelativePhysicalPath { get; }
|
||||
public override string RelativePhysicalPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_isRelativePhysicalPathSet)
|
||||
{
|
||||
_isRelativePhysicalPathSet = true;
|
||||
|
||||
if (Exists)
|
||||
{
|
||||
if (_root != null &&
|
||||
!string.IsNullOrEmpty(PhysicalPath) &&
|
||||
PhysicalPath.StartsWith(_root, StringComparison.OrdinalIgnoreCase) &&
|
||||
PhysicalPath.Length > _root.Length &&
|
||||
(PhysicalPath[_root.Length] == Path.DirectorySeparatorChar || PhysicalPath[_root.Length] == Path.AltDirectorySeparatorChar))
|
||||
{
|
||||
_relativePhysicalPath = PhysicalPath.Substring(_root.Length + 1); // Include leading separator
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _relativePhysicalPath;
|
||||
}
|
||||
}
|
||||
|
||||
public override Stream Read()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
|
||||
// Assert
|
||||
var failure = Assert.Single(compilationResult.CompilationFailures);
|
||||
Assert.Equal(viewPath, failure.SourceFilePath);
|
||||
Assert.Equal(Path.Combine("Views", "Home", "Index.cshtml"), failure.SourceFilePath);
|
||||
Assert.Collection(failure.Messages,
|
||||
message => Assert.StartsWith(
|
||||
@"Unterminated string literal.",
|
||||
|
|
@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
compilationResult.CompilationFailures,
|
||||
failure =>
|
||||
{
|
||||
Assert.Equal(viewPath, failure.SourceFilePath);
|
||||
Assert.Equal(Path.Combine("Views", "Home", "Index.cshtml"), failure.SourceFilePath);
|
||||
Assert.Collection(failure.Messages,
|
||||
message =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
{
|
||||
// Arrange
|
||||
var fileProvider = new TestFileProvider("BasePath");
|
||||
var file1 = fileProvider.AddFile("File1.txt", "content");
|
||||
var file2 = fileProvider.AddFile("File2.js", "content");
|
||||
var file1 = fileProvider.AddFile("/File1.txt", "content");
|
||||
var file2 = fileProvider.AddFile("/File2.js", "content");
|
||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2 });
|
||||
|
||||
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
||||
|
|
@ -37,9 +37,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
{
|
||||
// Arrange
|
||||
var fileProvider = new TestFileProvider("BasePath");
|
||||
var file1 = fileProvider.AddFile("File1.cshtml", "content");
|
||||
var file2 = fileProvider.AddFile("File2.js", "content");
|
||||
var file3 = fileProvider.AddFile("File3.cshtml", "content");
|
||||
var file1 = fileProvider.AddFile("/File1.cshtml", "content");
|
||||
var file2 = fileProvider.AddFile("/File2.js", "content");
|
||||
var file3 = fileProvider.AddFile("/File3.cshtml", "content");
|
||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });
|
||||
|
||||
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
||||
|
|
@ -84,9 +84,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
};
|
||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { directory1, file1, directory2 });
|
||||
|
||||
var file2 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File2.cshtml"), "content");
|
||||
var file3 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File3.cshtml"), "content");
|
||||
var file4 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File4.txt"), "content");
|
||||
var file2 = fileProvider.AddFile("/Level1-Dir1/File2.cshtml", "content");
|
||||
var file3 = fileProvider.AddFile("/Level1-Dir1/File3.cshtml", "content");
|
||||
var file4 = fileProvider.AddFile("/Level1-Dir1/File4.txt", "content");
|
||||
var directory3 = new TestDirectoryFileInfo
|
||||
{
|
||||
Name = "Level2-Dir1"
|
||||
|
|
@ -144,16 +144,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
{
|
||||
Name = "Level1-Dir1",
|
||||
};
|
||||
var file1 = fileProvider.AddFile(Path.Combine("BasePath", "File1.cshtml"), "content");
|
||||
var file1 = fileProvider.AddFile("/File1.cshtml", "content");
|
||||
var directory2 = new TestDirectoryFileInfo
|
||||
{
|
||||
Name = "Level1-Dir2",
|
||||
};
|
||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { directory1, file1, directory2 });
|
||||
|
||||
var file2 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File2.cshtml"), "content");
|
||||
var file3 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File3.cshtml"), "content");
|
||||
var file4 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File4.txt"), "content");
|
||||
var file2 = fileProvider.AddFile("/Level1-Dir1/File2.cshtml", "content");
|
||||
var file3 = fileProvider.AddFile("/Level1-Dir1/File3.cshtml", "content");
|
||||
var file4 = fileProvider.AddFile("/Level1-Dir1/File4.txt", "content");
|
||||
var directory3 = new TestDirectoryFileInfo
|
||||
{
|
||||
Name = "Level2-Dir1"
|
||||
|
|
@ -188,13 +188,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
});
|
||||
}
|
||||
|
||||
[Fact(Skip = "Need to follow-up https://github.com/aspnet/Mvc/pull/7228")]
|
||||
[Fact]
|
||||
public void GetItem_ReturnsFileFromDisk()
|
||||
{
|
||||
var fileProvider = new TestFileProvider("BasePath");
|
||||
var file1 = fileProvider.AddFile("File1.cshtml", "content");
|
||||
var file2 = fileProvider.AddFile("File2.js", "content");
|
||||
var file3 = fileProvider.AddFile("File3.cshtml", "content");
|
||||
var file1 = fileProvider.AddFile("/File1.cshtml", "content");
|
||||
var file2 = fileProvider.AddFile("/File2.js", "content");
|
||||
var file3 = fileProvider.AddFile("/File3.cshtml", "content");
|
||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });
|
||||
|
||||
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
||||
|
|
@ -212,12 +212,36 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
Assert.Equal("File3.cshtml", item.RelativePhysicalPath);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetItem_PhysicalPathDoesNotStartWithContentRoot_ReturnsNull()
|
||||
{
|
||||
var fileProvider = new TestFileProvider("BasePath2");
|
||||
var file1 = fileProvider.AddFile("/File1.cshtml", "content");
|
||||
var file2 = fileProvider.AddFile("/File2.js", "content");
|
||||
var file3 = fileProvider.AddFile("/File3.cshtml", "content");
|
||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });
|
||||
|
||||
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
||||
|
||||
var razorProject = new FileProviderRazorProject(accessor, Mock.Of<IHostingEnvironment>(e => e.ContentRootPath == "BasePath"));
|
||||
|
||||
// Act
|
||||
var item = razorProject.GetItem("/File3.cshtml");
|
||||
|
||||
// Assert
|
||||
Assert.True(item.Exists);
|
||||
Assert.Equal("/File3.cshtml", item.FilePath);
|
||||
Assert.Equal(string.Empty, item.BasePath);
|
||||
Assert.Equal(Path.Combine("BasePath2", "File3.cshtml"), item.PhysicalPath);
|
||||
Assert.Null(item.RelativePhysicalPath);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetItem_ReturnsNotFoundResult()
|
||||
{
|
||||
// Arrange
|
||||
var fileProvider = new TestFileProvider("BasePath");
|
||||
var file = fileProvider.AddFile("SomeFile.cshtml", "content");
|
||||
var file = fileProvider.AddFile("/SomeFile.cshtml", "content");
|
||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file });
|
||||
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
var fileInfo = new TestFileInfo
|
||||
{
|
||||
Content = contents,
|
||||
PhysicalPath = Path.Combine(Root, path),
|
||||
PhysicalPath = Path.Combine(Root, NormalizeAndEnsureValidPhysicalPath(path)),
|
||||
Name = Path.GetFileName(path),
|
||||
LastModified = DateTime.UtcNow,
|
||||
};
|
||||
|
|
@ -109,6 +109,23 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
return _fileTriggers[filter];
|
||||
}
|
||||
|
||||
private static string NormalizeAndEnsureValidPhysicalPath(string filePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
return filePath;
|
||||
}
|
||||
|
||||
filePath = filePath.Replace('/', Path.DirectorySeparatorChar);
|
||||
|
||||
if (filePath[0] == Path.DirectorySeparatorChar)
|
||||
{
|
||||
filePath = filePath.Substring(1);
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
private class NotFoundFileInfo : IFileInfo
|
||||
{
|
||||
public bool Exists
|
||||
|
|
|
|||
Loading…
Reference in New Issue