mirror of
https://github.com/lidarr/Lidarr
synced 2024-12-27 01:57:21 +00:00
Directory lookup will not include some folders at base of drive
This commit is contained in:
parent
485f05d4b9
commit
1c5e30bbd0
8 changed files with 202 additions and 57 deletions
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Common;
|
||||
|
@ -8,12 +10,12 @@ namespace NzbDrone.Api.Directories
|
|||
{
|
||||
public class DirectoryModule : NzbDroneApiModule
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IDirectoryLookupService _directoryLookupService;
|
||||
|
||||
public DirectoryModule(IDiskProvider diskProvider)
|
||||
public DirectoryModule(IDirectoryLookupService directoryLookupService)
|
||||
: base("/directories")
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
_directoryLookupService = directoryLookupService;
|
||||
Get["/"] = x => GetDirectories();
|
||||
}
|
||||
|
||||
|
@ -24,30 +26,7 @@ private Response GetDirectories()
|
|||
|
||||
string query = Request.Query.query.Value;
|
||||
|
||||
IEnumerable<String> dirs = null;
|
||||
try
|
||||
{
|
||||
//Windows (Including UNC)
|
||||
var windowsSep = query.LastIndexOf('\\');
|
||||
|
||||
if (windowsSep > -1)
|
||||
{
|
||||
dirs = _diskProvider.GetDirectories(query.Substring(0, windowsSep + 1));
|
||||
}
|
||||
|
||||
//Unix
|
||||
var index = query.LastIndexOf('/');
|
||||
|
||||
if (index > -1)
|
||||
{
|
||||
dirs = _diskProvider.GetDirectories(query.Substring(0, index + 1));
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Swallow the exceptions so proper JSON is returned to the client (Empty results)
|
||||
return new List<string>().AsResponse();
|
||||
}
|
||||
var dirs = _directoryLookupService.LookupSubDirectories(query);
|
||||
|
||||
if (dirs == null)
|
||||
throw new Exception("A valid path was not provided");
|
||||
|
|
102
NzbDrone.Common.Test/DirectoryLookupServiceFixture.cs
Normal file
102
NzbDrone.Common.Test/DirectoryLookupServiceFixture.cs
Normal file
|
@ -0,0 +1,102 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Common.Test
|
||||
{
|
||||
[TestFixture]
|
||||
public class DirectoryLookupServiceFixture :TestBase<DirectoryLookupService>
|
||||
{
|
||||
private const string RECYCLING_BIN = "$Recycle.Bin";
|
||||
private const string SYSTEM_VOLUME_INFORMATION = "System Volume Information";
|
||||
private List<String> _folders;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_folders = new List<String>
|
||||
{
|
||||
RECYCLING_BIN,
|
||||
"Chocolatey",
|
||||
"Documents and Settings",
|
||||
"Dropbox",
|
||||
"Intel",
|
||||
"PerfLogs",
|
||||
"Program Files",
|
||||
"Program Files (x86)",
|
||||
"ProgramData",
|
||||
SYSTEM_VOLUME_INFORMATION,
|
||||
"Test",
|
||||
"Users",
|
||||
"Windows"
|
||||
};
|
||||
}
|
||||
|
||||
private void SetupFolders(string root)
|
||||
{
|
||||
_folders.ForEach(e =>
|
||||
{
|
||||
e = Path.Combine(root, e);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_get_all_folder_for_none_root_path()
|
||||
{
|
||||
const string root = @"C:\Test\";
|
||||
SetupFolders(root);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetDirectories(It.IsAny<String>()))
|
||||
.Returns(_folders.ToArray());
|
||||
|
||||
Subject.LookupSubDirectories(root).Should()
|
||||
.HaveCount(_folders.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_contain_recycling_bin_for_root_of_drive()
|
||||
{
|
||||
const string root = @"C:\";
|
||||
SetupFolders(root);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetDirectories(It.IsAny<String>()))
|
||||
.Returns(_folders.ToArray());
|
||||
|
||||
Subject.LookupSubDirectories(root).Should().NotContain(Path.Combine(root, RECYCLING_BIN));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_contain_system_volume_information_for_root_of_drive()
|
||||
{
|
||||
const string root = @"C:\";
|
||||
SetupFolders(root);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetDirectories(It.IsAny<String>()))
|
||||
.Returns(_folders.ToArray());
|
||||
|
||||
Subject.LookupSubDirectories(root).Should().NotContain(Path.Combine(root, SYSTEM_VOLUME_INFORMATION));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_contain_recycling_bin_or_system_volume_information_for_root_of_drive()
|
||||
{
|
||||
const string root = @"C:\";
|
||||
SetupFolders(root);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(s => s.GetDirectories(It.IsAny<String>()))
|
||||
.Returns(_folders.ToArray());
|
||||
|
||||
Subject.LookupSubDirectories(root).Should().HaveCount(_folders.Count - 2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,6 +62,7 @@
|
|||
<Compile Include="CacheTests\CachedManagerFixture.cs" />
|
||||
<Compile Include="CacheTests\CachedFixture.cs" />
|
||||
<Compile Include="ConfigFileProviderTest.cs" />
|
||||
<Compile Include="DirectoryLookupServiceFixture.cs" />
|
||||
<Compile Include="EnsureTest\PathExtensionFixture.cs" />
|
||||
<Compile Include="EnvironmentTests\StartupArgumentsFixture.cs" />
|
||||
<Compile Include="EnvironmentTests\EnviromentProviderTest.cs" />
|
||||
|
|
62
NzbDrone.Common/DirectoryLookupService.cs
Normal file
62
NzbDrone.Common/DirectoryLookupService.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Common
|
||||
{
|
||||
public interface IDirectoryLookupService
|
||||
{
|
||||
List<String> LookupSubDirectories(string query);
|
||||
}
|
||||
|
||||
public class DirectoryLookupService : IDirectoryLookupService
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
|
||||
public DirectoryLookupService(IDiskProvider diskProvider)
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
}
|
||||
|
||||
public List<String> LookupSubDirectories(string query)
|
||||
{
|
||||
List<String> dirs = null;
|
||||
try
|
||||
{
|
||||
//Windows (Including UNC)
|
||||
var windowsSep = query.LastIndexOf('\\');
|
||||
|
||||
if (windowsSep > -1)
|
||||
{
|
||||
var path = query.Substring(0, windowsSep + 1);
|
||||
var dirsList = _diskProvider.GetDirectories(path).ToList();
|
||||
|
||||
if (Path.GetPathRoot(path).Equals(path, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var setToRemove = new HashSet<string> { "$Recycle.Bin", "System Volume Information" };
|
||||
dirsList.RemoveAll(x => setToRemove.Contains(new DirectoryInfo(x).Name));
|
||||
}
|
||||
|
||||
dirs = dirsList;
|
||||
}
|
||||
|
||||
//Unix
|
||||
var index = query.LastIndexOf('/');
|
||||
|
||||
if (index > -1)
|
||||
{
|
||||
dirs = _diskProvider.GetDirectories(query.Substring(0, index + 1)).ToList();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Swallow the exceptions so proper JSON is returned to the client (Empty results)
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return dirs;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -58,7 +58,7 @@ static extern bool GetDiskFreeSpaceEx(string lpDirectoryName,
|
|||
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public virtual DateTime GetLastFolderWrite(string path)
|
||||
public DateTime GetLastFolderWrite(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
|
@ -78,7 +78,7 @@ public virtual DateTime GetLastFolderWrite(string path)
|
|||
.Max(c => c.LastWriteTimeUtc);
|
||||
}
|
||||
|
||||
public virtual DateTime GetLastFileWrite(string path)
|
||||
public DateTime GetLastFileWrite(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
|
@ -89,7 +89,7 @@ public virtual DateTime GetLastFileWrite(string path)
|
|||
return new FileInfo(path).LastWriteTimeUtc;
|
||||
}
|
||||
|
||||
public virtual void EnsureFolder(string path)
|
||||
public void EnsureFolder(string path)
|
||||
{
|
||||
if (!FolderExists(path))
|
||||
{
|
||||
|
@ -97,13 +97,13 @@ public virtual void EnsureFolder(string path)
|
|||
}
|
||||
}
|
||||
|
||||
public virtual bool FolderExists(string path)
|
||||
public bool FolderExists(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
return Directory.Exists(path);
|
||||
}
|
||||
|
||||
public virtual bool FolderExists(string path, bool caseSensitive)
|
||||
public bool FolderExists(string path, bool caseSensitive)
|
||||
{
|
||||
if (caseSensitive)
|
||||
{
|
||||
|
@ -113,13 +113,13 @@ public virtual bool FolderExists(string path, bool caseSensitive)
|
|||
return FolderExists(path);
|
||||
}
|
||||
|
||||
public virtual bool FileExists(string path)
|
||||
public bool FileExists(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
return File.Exists(path);
|
||||
}
|
||||
|
||||
public virtual bool FileExists(string path, bool caseSensitive)
|
||||
public bool FileExists(string path, bool caseSensitive)
|
||||
{
|
||||
if (caseSensitive)
|
||||
{
|
||||
|
@ -129,28 +129,28 @@ public virtual bool FileExists(string path, bool caseSensitive)
|
|||
return FileExists(path);
|
||||
}
|
||||
|
||||
public virtual string[] GetDirectories(string path)
|
||||
public string[] GetDirectories(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
return Directory.GetDirectories(path);
|
||||
}
|
||||
|
||||
public virtual string[] GetFiles(string path, SearchOption searchOption)
|
||||
public string[] GetFiles(string path, SearchOption searchOption)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
return Directory.GetFiles(path, "*.*", searchOption);
|
||||
}
|
||||
|
||||
public virtual long GetFolderSize(string path)
|
||||
public long GetFolderSize(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
return GetFiles(path, SearchOption.AllDirectories).Sum(e => new FileInfo(e).Length);
|
||||
}
|
||||
|
||||
public virtual long GetFileSize(string path)
|
||||
public long GetFileSize(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
|
@ -161,14 +161,14 @@ public virtual long GetFileSize(string path)
|
|||
return fi.Length;
|
||||
}
|
||||
|
||||
public virtual String CreateFolder(string path)
|
||||
public String CreateFolder(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
return Directory.CreateDirectory(path).FullName;
|
||||
}
|
||||
|
||||
public virtual void CopyFolder(string source, string target)
|
||||
public void CopyFolder(string source, string target)
|
||||
{
|
||||
Ensure.That(() => source).IsValidPath();
|
||||
Ensure.That(() => target).IsValidPath();
|
||||
|
@ -176,7 +176,7 @@ public virtual void CopyFolder(string source, string target)
|
|||
TransferFolder(source, target, TransferAction.Copy);
|
||||
}
|
||||
|
||||
public virtual void MoveFolder(string source, string destination)
|
||||
public void MoveFolder(string source, string destination)
|
||||
{
|
||||
Ensure.That(() => source).IsValidPath();
|
||||
Ensure.That(() => destination).IsValidPath();
|
||||
|
@ -237,7 +237,7 @@ private void TransferFolder(string source, string target, TransferAction transfe
|
|||
}
|
||||
}
|
||||
|
||||
public virtual void DeleteFile(string path)
|
||||
public void DeleteFile(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
|
@ -245,7 +245,7 @@ public virtual void DeleteFile(string path)
|
|||
File.Delete(path);
|
||||
}
|
||||
|
||||
public virtual void MoveFile(string source, string destination)
|
||||
public void MoveFile(string source, string destination)
|
||||
{
|
||||
Ensure.That(() => source).IsValidPath();
|
||||
Ensure.That(() => destination).IsValidPath();
|
||||
|
@ -264,14 +264,14 @@ public virtual void MoveFile(string source, string destination)
|
|||
File.Move(source, destination);
|
||||
}
|
||||
|
||||
public virtual void DeleteFolder(string path, bool recursive)
|
||||
public void DeleteFolder(string path, bool recursive)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
Directory.Delete(path, recursive);
|
||||
}
|
||||
|
||||
public virtual void InheritFolderPermissions(string filename)
|
||||
public void InheritFolderPermissions(string filename)
|
||||
{
|
||||
Ensure.That(() => filename).IsValidPath();
|
||||
|
||||
|
@ -280,7 +280,7 @@ public virtual void InheritFolderPermissions(string filename)
|
|||
File.SetAccessControl(filename, fs);
|
||||
}
|
||||
|
||||
public virtual long GetAvilableSpace(string path)
|
||||
public long GetAvilableSpace(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
|
@ -327,14 +327,14 @@ private static long DriveFreeSpaceEx(string folderName)
|
|||
return 0;
|
||||
}
|
||||
|
||||
public virtual string ReadAllText(string filePath)
|
||||
public string ReadAllText(string filePath)
|
||||
{
|
||||
Ensure.That(() => filePath).IsValidPath();
|
||||
|
||||
return File.ReadAllText(filePath);
|
||||
}
|
||||
|
||||
public virtual void WriteAllText(string filename, string contents)
|
||||
public void WriteAllText(string filename, string contents)
|
||||
{
|
||||
Ensure.That(() => filename).IsValidPath();
|
||||
|
||||
|
@ -349,21 +349,21 @@ public static bool PathEquals(string firstPath, string secondPath)
|
|||
return String.Equals(firstPath.CleanFilePath(), secondPath.CleanFilePath(), StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public virtual void FileSetLastWriteTimeUtc(string path, DateTime dateTime)
|
||||
public void FileSetLastWriteTimeUtc(string path, DateTime dateTime)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
File.SetLastWriteTimeUtc(path, dateTime);
|
||||
}
|
||||
|
||||
public virtual void FolderSetLastWriteTimeUtc(string path, DateTime dateTime)
|
||||
public void FolderSetLastWriteTimeUtc(string path, DateTime dateTime)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
Directory.SetLastWriteTimeUtc(path, dateTime);
|
||||
}
|
||||
|
||||
public virtual bool IsFileLocked(FileInfo file)
|
||||
public bool IsFileLocked(FileInfo file)
|
||||
{
|
||||
FileStream stream = null;
|
||||
|
||||
|
@ -385,7 +385,7 @@ public virtual bool IsFileLocked(FileInfo file)
|
|||
return false;
|
||||
}
|
||||
|
||||
public virtual string GetPathRoot(string path)
|
||||
public string GetPathRoot(string path)
|
||||
{
|
||||
Ensure.That(() => path).IsValidPath();
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
<Compile Include="Composition\Container.cs" />
|
||||
<Compile Include="Composition\IContainer.cs" />
|
||||
<Compile Include="Composition\ContainerBuilderBase.cs" />
|
||||
<Compile Include="DirectoryLookupService.cs" />
|
||||
<Compile Include="EnsureThat\Ensure.cs" />
|
||||
<Compile Include="EnsureThat\EnsureBoolExtensions.cs" />
|
||||
<Compile Include="EnsureThat\EnsureCollectionExtensions.cs" />
|
||||
|
|
|
@ -109,7 +109,7 @@ public void should_not_delete_folder_if_no_files_were_imported()
|
|||
|
||||
Subject.Execute(new DownloadedEpisodesScanCommand());
|
||||
|
||||
Mocker.GetMock<DiskProvider>()
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Verify(v => v.GetFolderSize(It.IsAny<String>()), Times.Never());
|
||||
}
|
||||
|
||||
|
|
|
@ -85,13 +85,13 @@ public TModel Get(int id)
|
|||
|
||||
public IEnumerable<TModel> Get(IEnumerable<int> ids)
|
||||
{
|
||||
var query = String.Format("Id IN ({0})", String.Join(",", ids));
|
||||
|
||||
var idList = ids.ToList();
|
||||
var query = String.Format("Id IN ({0})", String.Join(",", idList));
|
||||
var result = Query.Where(query).ToList();
|
||||
|
||||
if (result.Count != ids.Count())
|
||||
if (result.Count != idList.Count())
|
||||
{
|
||||
throw new ApplicationException("Expected query to return {0} rows but returned {1}".Inject(ids.Count(), result.Count));
|
||||
throw new ApplicationException("Expected query to return {0} rows but returned {1}".Inject(idList.Count(), result.Count));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
Loading…
Reference in a new issue