mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-04-05 21:01:35 +08:00
Adjusting FileSystemStorageProvider path semantics
All path information coming in and out is within a tenant-specific location The location is now an implementation detail of the component --HG-- branch : dev
This commit is contained in:
parent
312d6d812c
commit
f60608368c
@ -3,43 +3,170 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Storage;
|
||||
|
||||
namespace Orchard.Tests.Storage {
|
||||
[TestFixture]
|
||||
public class FileSystemStorageProviderTests {
|
||||
#region Setup/Teardown
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void InitFixture() {
|
||||
_folderPath = Directory.CreateDirectory(Path.GetTempPath() + "filesystemstorageprovidertests").FullName;
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
_folderPath = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Media"), "Default");
|
||||
_filePath = _folderPath + "\\testfile.txt";
|
||||
FileStream fileStream = File.Create(_filePath);
|
||||
fileStream.Close();
|
||||
_fileSystemStorageProvider = new FileSystemStorageProvider();
|
||||
|
||||
Directory.CreateDirectory(_folderPath);
|
||||
File.WriteAllText(_filePath, "testfile contents");
|
||||
|
||||
var subfolder1 = Path.Combine(_folderPath, "Subfolder1");
|
||||
Directory.CreateDirectory(subfolder1);
|
||||
File.WriteAllText(Path.Combine(subfolder1, "one.txt"), "one contents");
|
||||
File.WriteAllText(Path.Combine(subfolder1, "two.txt"), "two contents");
|
||||
|
||||
var subsubfolder1 = Path.Combine(subfolder1, "SubSubfolder1");
|
||||
Directory.CreateDirectory(subsubfolder1);
|
||||
|
||||
_storageProvider = new FileSystemStorageProvider(new ShellSettings { Name = "Default" });
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void TermFixture() {
|
||||
[TearDown]
|
||||
public void Term() {
|
||||
Directory.Delete(_folderPath, true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string _filePath;
|
||||
private string _folderPath;
|
||||
private FileSystemStorageProvider _fileSystemStorageProvider;
|
||||
private IStorageProvider _storageProvider;
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void GetFileThatDoesNotExistShouldThrow() {
|
||||
_fileSystemStorageProvider.GetFile("notexisting");
|
||||
_storageProvider.GetFile("notexisting");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ListFilesShouldReturnFilesFromFilesystem() {
|
||||
IEnumerable<IStorageFile> files = _fileSystemStorageProvider.ListFiles(_folderPath);
|
||||
IEnumerable<IStorageFile> files = _storageProvider.ListFiles(_folderPath);
|
||||
Assert.That(files.Count(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExistingFileIsReturnedWithShortPath() {
|
||||
var file = _storageProvider.GetFile("testfile.txt");
|
||||
Assert.That(file, Is.Not.Null);
|
||||
Assert.That(file.GetPath(), Is.EqualTo("testfile.txt"));
|
||||
Assert.That(file.GetName(), Is.EqualTo("testfile.txt"));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ListFilesReturnsItemsWithShortPathAndEnvironmentSlashes() {
|
||||
var files = _storageProvider.ListFiles("Subfolder1");
|
||||
Assert.That(files, Is.Not.Null);
|
||||
Assert.That(files.Count(), Is.EqualTo(2));
|
||||
var one = files.Single(x => x.GetName() == "one.txt");
|
||||
var two = files.Single(x => x.GetName() == "two.txt");
|
||||
|
||||
Assert.That(one.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "one.txt"));
|
||||
Assert.That(two.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "two.txt"));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void AnySlashInGetFileBecomesEnvironmentAppropriate() {
|
||||
var file1 = _storageProvider.GetFile(@"Subfolder1/one.txt");
|
||||
var file2 = _storageProvider.GetFile(@"Subfolder1\one.txt");
|
||||
Assert.That(file1.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "one.txt"));
|
||||
Assert.That(file2.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "one.txt"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ListFoldersReturnsItemsWithShortPathAndEnvironmentSlashes() {
|
||||
var folders = _storageProvider.ListFolders(@"Subfolder1");
|
||||
Assert.That(folders, Is.Not.Null);
|
||||
Assert.That(folders.Count(), Is.EqualTo(1));
|
||||
Assert.That(folders.Single().GetName(), Is.EqualTo("SubSubfolder1"));
|
||||
Assert.That(folders.Single().GetPath(), Is.EqualTo(Path.Combine("Subfolder1", "SubSubfolder1")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParentFolderPathIsStillShort() {
|
||||
var subsubfolder = _storageProvider.ListFolders(@"Subfolder1").Single();
|
||||
var subfolder = subsubfolder.GetParent();
|
||||
Assert.That(subsubfolder.GetName(), Is.EqualTo("SubSubfolder1"));
|
||||
Assert.That(subsubfolder.GetPath(), Is.EqualTo(Path.Combine("Subfolder1", "SubSubfolder1")));
|
||||
Assert.That(subfolder.GetName(), Is.EqualTo("Subfolder1"));
|
||||
Assert.That(subfolder.GetPath(), Is.EqualTo("Subfolder1"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateFolderAndDeleteFolderTakesAnySlash() {
|
||||
Assert.That(_storageProvider.ListFolders(@"Subfolder1").Count(), Is.EqualTo(1));
|
||||
_storageProvider.CreateFolder(@"SubFolder1/SubSubFolder2");
|
||||
_storageProvider.CreateFolder(@"SubFolder1\SubSubFolder3");
|
||||
Assert.That(_storageProvider.ListFolders(@"Subfolder1").Count(), Is.EqualTo(3));
|
||||
_storageProvider.DeleteFolder(@"SubFolder1/SubSubFolder2");
|
||||
_storageProvider.DeleteFolder(@"SubFolder1\SubSubFolder3");
|
||||
Assert.That(_storageProvider.ListFolders(@"Subfolder1").Count(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
private IStorageFolder GetFolder(string path) {
|
||||
return _storageProvider.ListFolders(Path.GetDirectoryName(path))
|
||||
.SingleOrDefault(x => string.Equals(x.GetName(), Path.GetFileName(path), StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
private IStorageFile GetFile(string path) {
|
||||
try {
|
||||
return _storageProvider.GetFile(path);
|
||||
}
|
||||
catch (ArgumentException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RenameFolderTakesShortPathWithAnyKindOfSlash() {
|
||||
Assert.That(GetFolder(@"SubFolder1/SubSubFolder1"), Is.Not.Null);
|
||||
_storageProvider.RenameFolder(@"SubFolder1\SubSubFolder1", @"SubFolder1/SubSubFolder2");
|
||||
_storageProvider.RenameFolder(@"SubFolder1\SubSubFolder2", @"SubFolder1\SubSubFolder3");
|
||||
_storageProvider.RenameFolder(@"SubFolder1/SubSubFolder3", @"SubFolder1\SubSubFolder4");
|
||||
_storageProvider.RenameFolder(@"SubFolder1/SubSubFolder4", @"SubFolder1/SubSubFolder5");
|
||||
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder1")), Is.Null);
|
||||
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder2")), Is.Null);
|
||||
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder3")), Is.Null);
|
||||
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder4")), Is.Null);
|
||||
Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder5")), Is.Not.Null);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void CreateFileAndDeleteFileTakesAnySlash() {
|
||||
Assert.That(_storageProvider.ListFiles(@"Subfolder1").Count(), Is.EqualTo(2));
|
||||
var alpha = _storageProvider.CreateFile(@"SubFolder1/alpha.txt");
|
||||
var beta = _storageProvider.CreateFile(@"SubFolder1\beta.txt");
|
||||
Assert.That(_storageProvider.ListFiles(@"Subfolder1").Count(), Is.EqualTo(4));
|
||||
Assert.That(alpha.GetPath(), Is.EqualTo(Path.Combine("SubFolder1", "alpha.txt")));
|
||||
Assert.That(beta.GetPath(), Is.EqualTo(Path.Combine("SubFolder1", "beta.txt")));
|
||||
_storageProvider.DeleteFile(@"SubFolder1\alpha.txt");
|
||||
_storageProvider.DeleteFile(@"SubFolder1/beta.txt");
|
||||
Assert.That(_storageProvider.ListFiles(@"Subfolder1").Count(), Is.EqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RenameFileTakesShortPathWithAnyKindOfSlash() {
|
||||
Assert.That(GetFile(@"Subfolder1/one.txt"), Is.Not.Null);
|
||||
_storageProvider.RenameFile(@"SubFolder1\one.txt", @"SubFolder1/testfile2.txt");
|
||||
_storageProvider.RenameFile(@"SubFolder1\testfile2.txt", @"SubFolder1\testfile3.txt");
|
||||
_storageProvider.RenameFile(@"SubFolder1/testfile3.txt", @"SubFolder1\testfile4.txt");
|
||||
_storageProvider.RenameFile(@"SubFolder1/testfile4.txt", @"SubFolder1/testfile5.txt");
|
||||
Assert.That(GetFile(Path.Combine("SubFolder1", "one.txt")), Is.Null);
|
||||
Assert.That(GetFile(Path.Combine("SubFolder1", "testfile2.txt")), Is.Null);
|
||||
Assert.That(GetFile(Path.Combine("SubFolder1", "testfile3.txt")), Is.Null);
|
||||
Assert.That(GetFile(Path.Combine("SubFolder1", "testfile4.txt")), Is.Null);
|
||||
Assert.That(GetFile(Path.Combine("SubFolder1", "testfile5.txt")), Is.Not.Null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -102,6 +102,10 @@
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Tools\Orchard\Orchard.csproj">
|
||||
<Project>{33B1BC8D-E292-4972-A363-22056B207156}</Project>
|
||||
<Name>Orchard</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="Core\Orchard.Core.csproj">
|
||||
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
|
||||
<Name>Orchard.Core</Name>
|
||||
|
@ -2,44 +2,68 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Hosting;
|
||||
using Orchard.Environment.Configuration;
|
||||
|
||||
namespace Orchard.Storage {
|
||||
public class FileSystemStorageProvider : IStorageProvider {
|
||||
private readonly ShellSettings _settings;
|
||||
private string _storagePath;
|
||||
|
||||
public FileSystemStorageProvider(ShellSettings settings) {
|
||||
_settings = settings;
|
||||
|
||||
var mediaPath = HostingEnvironment.IsHosted
|
||||
? HostingEnvironment.MapPath("~/Media/")
|
||||
: Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Media");
|
||||
_storagePath = Path.Combine(mediaPath, settings.Name);
|
||||
}
|
||||
|
||||
string Map(string path) {
|
||||
return Path.Combine(_storagePath, path);
|
||||
}
|
||||
|
||||
static string Fix(string path) {
|
||||
return Path.DirectorySeparatorChar != '/'
|
||||
? path.Replace('/', Path.DirectorySeparatorChar)
|
||||
: path;
|
||||
}
|
||||
|
||||
#region Implementation of IStorageProvider
|
||||
|
||||
public IStorageFile GetFile(string path) {
|
||||
if (!File.Exists(path)) {
|
||||
if (!File.Exists(Map(path))) {
|
||||
throw new ArgumentException("File " + path + " does not exist");
|
||||
}
|
||||
return new FileSystemStorageFile(new FileInfo(path));
|
||||
return new FileSystemStorageFile(Fix(path), new FileInfo(Map(path)));
|
||||
}
|
||||
|
||||
public IEnumerable<IStorageFile> ListFiles(string path) {
|
||||
if (!Directory.Exists(path)) {
|
||||
if (!Directory.Exists(Map(path))) {
|
||||
throw new ArgumentException("Directory " + path + " does not exist");
|
||||
}
|
||||
|
||||
return new DirectoryInfo(path)
|
||||
return new DirectoryInfo(Map(path))
|
||||
.GetFiles()
|
||||
.Where(fi => !IsHidden(fi))
|
||||
.Select<FileInfo, IStorageFile>(fi => new FileSystemStorageFile(fi))
|
||||
.Select<FileInfo, IStorageFile>(fi => new FileSystemStorageFile(Path.Combine(Fix(path), fi.Name), fi))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<IStorageFolder> ListFolders(string path) {
|
||||
if (!Directory.Exists(path)) {
|
||||
if (!Directory.Exists(Map(path))) {
|
||||
try {
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
Directory.CreateDirectory(Map(path));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ArgumentException(string.Format("The folder could not be created at path: {0}. {1}",path,ex));
|
||||
throw new ArgumentException(string.Format("The folder could not be created at path: {0}. {1}", path, ex));
|
||||
}
|
||||
}
|
||||
|
||||
return new DirectoryInfo(path)
|
||||
return new DirectoryInfo(Map(path))
|
||||
.GetDirectories()
|
||||
.Where(di => !IsHidden(di))
|
||||
.Select<DirectoryInfo, IStorageFolder>(di => new FileSystemStorageFolder(di))
|
||||
.Select<DirectoryInfo, IStorageFolder>(di => new FileSystemStorageFolder(Path.Combine(Fix(path), di.Name), di))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
@ -48,81 +72,80 @@ namespace Orchard.Storage {
|
||||
}
|
||||
|
||||
public void CreateFolder(string path) {
|
||||
if (Directory.Exists(path)) {
|
||||
if (Directory.Exists(Map(path))) {
|
||||
throw new ArgumentException("Directory " + path + " already exists");
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(Map(path));
|
||||
}
|
||||
|
||||
public void DeleteFolder(string path) {
|
||||
if (!Directory.Exists(path)) {
|
||||
if (!Directory.Exists(Map(path))) {
|
||||
throw new ArgumentException("Directory " + path + " does not exist");
|
||||
}
|
||||
|
||||
Directory.Delete(path, true);
|
||||
Directory.Delete(Map(path), true);
|
||||
}
|
||||
|
||||
public void RenameFolder(string path, string newPath) {
|
||||
if (!Directory.Exists(path)) {
|
||||
if (!Directory.Exists(Map(path))) {
|
||||
throw new ArgumentException("Directory " + path + "does not exist");
|
||||
}
|
||||
|
||||
if (Directory.Exists(newPath)) {
|
||||
if (Directory.Exists(Map(newPath))) {
|
||||
throw new ArgumentException("Directory " + newPath + " already exists");
|
||||
}
|
||||
|
||||
Directory.Move(path, newPath);
|
||||
Directory.Move(Map(path), Map(newPath));
|
||||
}
|
||||
|
||||
public IStorageFile CreateFile(string path) {
|
||||
if (File.Exists(path)) {
|
||||
if (File.Exists(Map(path))) {
|
||||
throw new ArgumentException("File " + path + " already exists");
|
||||
}
|
||||
|
||||
var fileInfo = new FileInfo(path);
|
||||
fileInfo.Create();
|
||||
return new FileSystemStorageFile(fileInfo);
|
||||
var fileInfo = new FileInfo(Map(path));
|
||||
using (var stream = fileInfo.Create()) {
|
||||
|
||||
}
|
||||
return new FileSystemStorageFile(Fix(path), fileInfo);
|
||||
}
|
||||
|
||||
public void DeleteFile(string path) {
|
||||
if (!File.Exists(path)) {
|
||||
if (!File.Exists(Map(path))) {
|
||||
throw new ArgumentException("File " + path + " does not exist");
|
||||
}
|
||||
|
||||
File.Delete(path);
|
||||
File.Delete(Map(path));
|
||||
}
|
||||
|
||||
public void RenameFile(string path, string newPath) {
|
||||
if (!File.Exists(path)) {
|
||||
if (!File.Exists(Map(path))) {
|
||||
throw new ArgumentException("File " + path + " does not exist");
|
||||
}
|
||||
|
||||
if (File.Exists(newPath)) {
|
||||
if (File.Exists(Map(newPath))) {
|
||||
throw new ArgumentException("File " + newPath + " already exists");
|
||||
}
|
||||
|
||||
File.Move(path, newPath);
|
||||
}
|
||||
|
||||
public string Combine(string path1, string path2)
|
||||
{
|
||||
return Path.Combine(path1, path2);
|
||||
File.Move(Map(path), Map(newPath));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private class FileSystemStorageFile : IStorageFile {
|
||||
private readonly string _path;
|
||||
private readonly FileInfo _fileInfo;
|
||||
|
||||
public FileSystemStorageFile(FileInfo fileInfo) {
|
||||
public FileSystemStorageFile(string path, FileInfo fileInfo) {
|
||||
_path = path;
|
||||
_fileInfo = fileInfo;
|
||||
}
|
||||
|
||||
#region Implementation of IStorageFile
|
||||
|
||||
public string GetPath() {
|
||||
return _fileInfo.FullName;
|
||||
return _path;
|
||||
}
|
||||
|
||||
public string GetName() {
|
||||
@ -141,13 +164,11 @@ namespace Orchard.Storage {
|
||||
return _fileInfo.Extension;
|
||||
}
|
||||
|
||||
public Stream OpenRead()
|
||||
{
|
||||
public Stream OpenRead() {
|
||||
return new FileStream(_fileInfo.FullName, FileMode.Open, FileAccess.Read);
|
||||
}
|
||||
|
||||
public Stream OpenWrite()
|
||||
{
|
||||
public Stream OpenWrite() {
|
||||
return new FileStream(_fileInfo.FullName, FileMode.Open, FileAccess.ReadWrite);
|
||||
}
|
||||
|
||||
@ -155,14 +176,20 @@ namespace Orchard.Storage {
|
||||
}
|
||||
|
||||
private class FileSystemStorageFolder : IStorageFolder {
|
||||
private readonly string _path;
|
||||
private readonly DirectoryInfo _directoryInfo;
|
||||
|
||||
public FileSystemStorageFolder(DirectoryInfo directoryInfo) {
|
||||
public FileSystemStorageFolder(string path, DirectoryInfo directoryInfo) {
|
||||
_path = path;
|
||||
_directoryInfo = directoryInfo;
|
||||
}
|
||||
|
||||
#region Implementation of IStorageFolder
|
||||
|
||||
public string GetPath() {
|
||||
return _path;
|
||||
}
|
||||
|
||||
public string GetName() {
|
||||
return _directoryInfo.Name;
|
||||
}
|
||||
@ -177,7 +204,7 @@ namespace Orchard.Storage {
|
||||
|
||||
public IStorageFolder GetParent() {
|
||||
if (_directoryInfo.Parent != null) {
|
||||
return new FileSystemStorageFolder(_directoryInfo.Parent);
|
||||
return new FileSystemStorageFolder(Path.GetDirectoryName(_path), _directoryInfo.Parent);
|
||||
}
|
||||
throw new ArgumentException("Directory " + _directoryInfo.Name + " does not have a parent directory");
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Orchard.Storage {
|
||||
public interface IStorageFolder {
|
||||
string GetPath();
|
||||
string GetName();
|
||||
long GetSize();
|
||||
DateTime GetLastUpdated();
|
||||
|
Loading…
Reference in New Issue
Block a user