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);
|
path = NormalizeAndEnsureValidPath(path);
|
||||||
var fileInfo = _provider.GetFileInfo(path);
|
var fileInfo = _provider.GetFileInfo(path);
|
||||||
|
|
||||||
string relativePhysicalPath = null;
|
return new FileProviderRazorProjectItem(fileInfo, basePath: string.Empty, filePath: path, root: _hostingEnvironment.ContentRootPath);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<RazorProjectItem> EnumerateItems(string path)
|
public override IEnumerable<RazorProjectItem> EnumerateItems(string path)
|
||||||
|
|
@ -58,11 +50,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
{
|
{
|
||||||
if (directory.Exists)
|
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 subDirectory = _provider.GetDirectoryContents(JoinPath(basePath, relativePath));
|
||||||
var children = EnumerateFiles(subDirectory, basePath, relativePath);
|
var children = EnumerateFiles(subDirectory, basePath, relativePath);
|
||||||
foreach (var child in children)
|
foreach (var child in children)
|
||||||
|
|
@ -70,14 +62,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
yield return child;
|
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 filePath = prefix + "/" + fileInfo.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
|
|
||||||
|
|
||||||
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.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
using Microsoft.AspNetCore.Razor.Language;
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
|
@ -9,12 +10,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
{
|
{
|
||||||
public class FileProviderRazorProjectItem : RazorProjectItem
|
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;
|
FileInfo = fileInfo;
|
||||||
BasePath = basePath;
|
BasePath = basePath;
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
RelativePhysicalPath = relativePhysicalPath;
|
_root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IFileInfo FileInfo { get; }
|
public IFileInfo FileInfo { get; }
|
||||||
|
|
@ -27,7 +32,30 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
|
|
||||||
public override string PhysicalPath => FileInfo.PhysicalPath;
|
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()
|
public override Stream Read()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var failure = Assert.Single(compilationResult.CompilationFailures);
|
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,
|
Assert.Collection(failure.Messages,
|
||||||
message => Assert.StartsWith(
|
message => Assert.StartsWith(
|
||||||
@"Unterminated string literal.",
|
@"Unterminated string literal.",
|
||||||
|
|
@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
compilationResult.CompilationFailures,
|
compilationResult.CompilationFailures,
|
||||||
failure =>
|
failure =>
|
||||||
{
|
{
|
||||||
Assert.Equal(viewPath, failure.SourceFilePath);
|
Assert.Equal(Path.Combine("Views", "Home", "Index.cshtml"), failure.SourceFilePath);
|
||||||
Assert.Collection(failure.Messages,
|
Assert.Collection(failure.Messages,
|
||||||
message =>
|
message =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var fileProvider = new TestFileProvider("BasePath");
|
var fileProvider = new TestFileProvider("BasePath");
|
||||||
var file1 = fileProvider.AddFile("File1.txt", "content");
|
var file1 = fileProvider.AddFile("/File1.txt", "content");
|
||||||
var file2 = fileProvider.AddFile("File2.js", "content");
|
var file2 = fileProvider.AddFile("/File2.js", "content");
|
||||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2 });
|
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2 });
|
||||||
|
|
||||||
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
||||||
|
|
@ -37,9 +37,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var fileProvider = new TestFileProvider("BasePath");
|
var fileProvider = new TestFileProvider("BasePath");
|
||||||
var file1 = fileProvider.AddFile("File1.cshtml", "content");
|
var file1 = fileProvider.AddFile("/File1.cshtml", "content");
|
||||||
var file2 = fileProvider.AddFile("File2.js", "content");
|
var file2 = fileProvider.AddFile("/File2.js", "content");
|
||||||
var file3 = fileProvider.AddFile("File3.cshtml", "content");
|
var file3 = fileProvider.AddFile("/File3.cshtml", "content");
|
||||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });
|
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });
|
||||||
|
|
||||||
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
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 });
|
fileProvider.AddDirectoryContent("/", new IFileInfo[] { directory1, file1, directory2 });
|
||||||
|
|
||||||
var file2 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File2.cshtml"), "content");
|
var file2 = fileProvider.AddFile("/Level1-Dir1/File2.cshtml", "content");
|
||||||
var file3 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File3.cshtml"), "content");
|
var file3 = fileProvider.AddFile("/Level1-Dir1/File3.cshtml", "content");
|
||||||
var file4 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File4.txt"), "content");
|
var file4 = fileProvider.AddFile("/Level1-Dir1/File4.txt", "content");
|
||||||
var directory3 = new TestDirectoryFileInfo
|
var directory3 = new TestDirectoryFileInfo
|
||||||
{
|
{
|
||||||
Name = "Level2-Dir1"
|
Name = "Level2-Dir1"
|
||||||
|
|
@ -144,16 +144,16 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
{
|
{
|
||||||
Name = "Level1-Dir1",
|
Name = "Level1-Dir1",
|
||||||
};
|
};
|
||||||
var file1 = fileProvider.AddFile(Path.Combine("BasePath", "File1.cshtml"), "content");
|
var file1 = fileProvider.AddFile("/File1.cshtml", "content");
|
||||||
var directory2 = new TestDirectoryFileInfo
|
var directory2 = new TestDirectoryFileInfo
|
||||||
{
|
{
|
||||||
Name = "Level1-Dir2",
|
Name = "Level1-Dir2",
|
||||||
};
|
};
|
||||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { directory1, file1, directory2 });
|
fileProvider.AddDirectoryContent("/", new IFileInfo[] { directory1, file1, directory2 });
|
||||||
|
|
||||||
var file2 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File2.cshtml"), "content");
|
var file2 = fileProvider.AddFile("/Level1-Dir1/File2.cshtml", "content");
|
||||||
var file3 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File3.cshtml"), "content");
|
var file3 = fileProvider.AddFile("/Level1-Dir1/File3.cshtml", "content");
|
||||||
var file4 = fileProvider.AddFile(Path.Combine("Level1-Dir1", "File4.txt"), "content");
|
var file4 = fileProvider.AddFile("/Level1-Dir1/File4.txt", "content");
|
||||||
var directory3 = new TestDirectoryFileInfo
|
var directory3 = new TestDirectoryFileInfo
|
||||||
{
|
{
|
||||||
Name = "Level2-Dir1"
|
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()
|
public void GetItem_ReturnsFileFromDisk()
|
||||||
{
|
{
|
||||||
var fileProvider = new TestFileProvider("BasePath");
|
var fileProvider = new TestFileProvider("BasePath");
|
||||||
var file1 = fileProvider.AddFile("File1.cshtml", "content");
|
var file1 = fileProvider.AddFile("/File1.cshtml", "content");
|
||||||
var file2 = fileProvider.AddFile("File2.js", "content");
|
var file2 = fileProvider.AddFile("/File2.js", "content");
|
||||||
var file3 = fileProvider.AddFile("File3.cshtml", "content");
|
var file3 = fileProvider.AddFile("/File3.cshtml", "content");
|
||||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });
|
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file1, file2, file3 });
|
||||||
|
|
||||||
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
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);
|
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]
|
[Fact]
|
||||||
public void GetItem_ReturnsNotFoundResult()
|
public void GetItem_ReturnsNotFoundResult()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var fileProvider = new TestFileProvider("BasePath");
|
var fileProvider = new TestFileProvider("BasePath");
|
||||||
var file = fileProvider.AddFile("SomeFile.cshtml", "content");
|
var file = fileProvider.AddFile("/SomeFile.cshtml", "content");
|
||||||
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file });
|
fileProvider.AddDirectoryContent("/", new IFileInfo[] { file });
|
||||||
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
var accessor = Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == fileProvider);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
var fileInfo = new TestFileInfo
|
var fileInfo = new TestFileInfo
|
||||||
{
|
{
|
||||||
Content = contents,
|
Content = contents,
|
||||||
PhysicalPath = Path.Combine(Root, path),
|
PhysicalPath = Path.Combine(Root, NormalizeAndEnsureValidPhysicalPath(path)),
|
||||||
Name = Path.GetFileName(path),
|
Name = Path.GetFileName(path),
|
||||||
LastModified = DateTime.UtcNow,
|
LastModified = DateTime.UtcNow,
|
||||||
};
|
};
|
||||||
|
|
@ -109,6 +109,23 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
return _fileTriggers[filter];
|
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
|
private class NotFoundFileInfo : IFileInfo
|
||||||
{
|
{
|
||||||
public bool Exists
|
public bool Exists
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue