Skip to content

Commit

Permalink
New: Ignore inaccessible files with getting files
Browse files Browse the repository at this point in the history
(cherry picked from commit e5aa8584100d96a2077c57f74ae5b2ceab63de19)
  • Loading branch information
markus101 authored and mynameisbogdan committed Aug 5, 2023
1 parent 1245b2c commit 5fc1fc4
Show file tree
Hide file tree
Showing 29 changed files with 113 additions and 80 deletions.
2 changes: 1 addition & 1 deletion src/Lidarr.Api.V1/Logs/LogFileController.cs
Expand Up @@ -25,7 +25,7 @@ public class LogFileController : LogFileControllerBase

protected override IEnumerable<string> GetLogFiles()
{
return _diskProvider.GetFiles(_appFolderInfo.GetLogFolder(), SearchOption.TopDirectoryOnly);
return _diskProvider.GetFiles(_appFolderInfo.GetLogFolder(), false);
}

protected override string GetLogFilePath(string filename)
Expand Down
2 changes: 1 addition & 1 deletion src/Lidarr.Api.V1/Logs/UpdateLogFileController.cs
Expand Up @@ -32,7 +32,7 @@ protected override IEnumerable<string> GetLogFiles()
return Enumerable.Empty<string>();
}

return _diskProvider.GetFiles(_appFolderInfo.GetUpdateLogFolder(), SearchOption.TopDirectoryOnly)
return _diskProvider.GetFiles(_appFolderInfo.GetUpdateLogFolder(), false)
.Where(f => Regex.IsMatch(Path.GetFileName(f), LOGFILE_ROUTE.TrimStart('/'), RegexOptions.IgnoreCase))
.ToList();
}
Expand Down
Expand Up @@ -838,7 +838,7 @@ private void WithEmulatedDiskProvider()

// Note: never returns anything.
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.GetFileInfos(It.IsAny<string>(), It.IsAny<SearchOption>()))
.Setup(v => v.GetFileInfos(It.IsAny<string>(), It.IsAny<bool>()))
.Returns(new List<IFileInfo>());

Mocker.GetMock<IDiskProvider>()
Expand Down Expand Up @@ -878,8 +878,8 @@ private void WithRealDiskProvider()
.Returns<string>(v => fileSystem.DirectoryInfo.FromDirectoryName(v).GetDirectories().ToList());

Mocker.GetMock<IDiskProvider>()
.Setup(v => v.GetFileInfos(It.IsAny<string>(), It.IsAny<SearchOption>()))
.Returns((string v, SearchOption option) => fileSystem.DirectoryInfo.FromDirectoryName(v).GetFiles("*", option).ToList());
.Setup(v => v.GetFileInfos(It.IsAny<string>(), It.IsAny<bool>()))
.Returns((string v, bool recursive) => fileSystem.DirectoryInfo.FromDirectoryName(v).GetFiles("*", new EnumerationOptions { RecurseSubdirectories = recursive }).ToList());

Mocker.GetMock<IDiskProvider>()
.Setup(v => v.GetFileSize(It.IsAny<string>()))
Expand Down
5 changes: 3 additions & 2 deletions src/NzbDrone.Common/ArchiveService.cs
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.GZip;
Expand All @@ -11,7 +12,7 @@ namespace NzbDrone.Common
public interface IArchiveService
{
void Extract(string compressedFile, string destination);
void CreateZip(string path, params string[] files);
void CreateZip(string path, IEnumerable<string> files);
}

public class ArchiveService : IArchiveService
Expand Down Expand Up @@ -39,7 +40,7 @@ public void Extract(string compressedFile, string destination)
_logger.Debug("Extraction complete.");
}

public void CreateZip(string path, params string[] files)
public void CreateZip(string path, IEnumerable<string> files)
{
using (var zipFile = ZipFile.Create(path))
{
Expand Down
31 changes: 20 additions & 11 deletions src/NzbDrone.Common/Disk/DiskProviderBase.cs
Expand Up @@ -53,7 +53,7 @@ public DateTime FolderGetLastWrite(string path)
{
CheckFolderExists(path);

var dirFiles = GetFiles(path, SearchOption.AllDirectories).ToList();
var dirFiles = GetFiles(path, true).ToList();

if (!dirFiles.Any())
{
Expand Down Expand Up @@ -156,11 +156,11 @@ public bool FolderEmpty(string path)
return _fileSystem.Directory.EnumerateFileSystemEntries(path).Empty();
}

public string[] GetDirectories(string path)
public IEnumerable<string> GetDirectories(string path)
{
Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs);

return _fileSystem.Directory.GetDirectories(path);
return _fileSystem.Directory.EnumerateDirectories(path);
}

public string[] GetDirectories(string path, SearchOption searchOption)
Expand All @@ -170,18 +170,22 @@ public string[] GetDirectories(string path, SearchOption searchOption)
return _fileSystem.Directory.GetDirectories(path, "*", searchOption);
}

public string[] GetFiles(string path, SearchOption searchOption)
public IEnumerable<string> GetFiles(string path, bool recursive)
{
Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs);

return _fileSystem.Directory.GetFiles(path, "*.*", searchOption);
return _fileSystem.Directory.EnumerateFiles(path, "*", new EnumerationOptions
{
RecurseSubdirectories = recursive,
IgnoreInaccessible = true
});
}

public long GetFolderSize(string path)
{
Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs);

return GetFiles(path, SearchOption.AllDirectories).Sum(e => _fileSystem.FileInfo.FromFileName(e).Length);
return GetFiles(path, true).Sum(e => _fileSystem.FileInfo.FromFileName(e).Length);
}

public long GetFileSize(string path)
Expand Down Expand Up @@ -302,8 +306,9 @@ public void DeleteFolder(string path, bool recursive)
{
Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs);

var files = _fileSystem.Directory.GetFiles(path, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
Array.ForEach(files, RemoveReadOnly);
var files = GetFiles(path, recursive);

files.ToList().ForEach(RemoveReadOnly);

_fileSystem.Directory.Delete(path, recursive);
}
Expand Down Expand Up @@ -404,7 +409,7 @@ public void EmptyFolder(string path)
{
Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs);

foreach (var file in GetFiles(path, SearchOption.TopDirectoryOnly))
foreach (var file in GetFiles(path, false))
{
DeleteFile(file);
}
Expand Down Expand Up @@ -504,13 +509,17 @@ public IDirectoryInfo GetDirectoryInfo(string path)
return _fileSystem.DirectoryInfo.FromDirectoryName(path);
}

public List<IFileInfo> GetFileInfos(string path, SearchOption searchOption = SearchOption.TopDirectoryOnly)
public List<IFileInfo> GetFileInfos(string path, bool recursive = false)
{
Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs);

var di = _fileSystem.DirectoryInfo.FromDirectoryName(path);

return di.GetFiles("*", searchOption).ToList();
return di.EnumerateFiles("*", new EnumerationOptions
{
RecurseSubdirectories = recursive,
IgnoreInaccessible = true
}).ToList();
}

public IFileInfo GetFileInfo(string path)
Expand Down
6 changes: 3 additions & 3 deletions src/NzbDrone.Common/Disk/IDiskProvider.cs
Expand Up @@ -23,8 +23,8 @@ public interface IDiskProvider
bool FileExists(string path, StringComparison stringComparison);
bool FolderWritable(string path);
bool FolderEmpty(string path);
string[] GetDirectories(string path);
string[] GetFiles(string path, SearchOption searchOption);
IEnumerable<string> GetDirectories(string path);
IEnumerable<string> GetFiles(string path, bool recursive);
long GetFolderSize(string path);
long GetFileSize(string path);
void CreateFolder(string path);
Expand Down Expand Up @@ -54,7 +54,7 @@ public interface IDiskProvider
IDirectoryInfo GetDirectoryInfo(string path);
List<IDirectoryInfo> GetDirectoryInfos(string path);
IFileInfo GetFileInfo(string path);
List<IFileInfo> GetFileInfos(string path, SearchOption searchOption = SearchOption.TopDirectoryOnly);
List<IFileInfo> GetFileInfos(string path, bool recursive = false);
void RemoveEmptySubfolders(string path);
void SaveStream(Stream stream, string path);
bool IsValidFolderPermissionMask(string mask);
Expand Down
Expand Up @@ -30,7 +30,7 @@ protected void GivenCompletedItem()
.Returns(new[] { targetDir });

Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
.Setup(c => c.GetFiles(targetDir, true))
.Returns(new[] { Path.Combine(targetDir, "somefile.flac") });

Mocker.GetMock<IDiskProvider>()
Expand Down
Expand Up @@ -83,7 +83,7 @@ protected void GivenCompletedItem()
.Returns(new[] { targetDir });

Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
.Setup(c => c.GetFiles(targetDir, true))
.Returns(new[] { Path.Combine(targetDir, "somefile.flac") });

Mocker.GetMock<IDiskProvider>()
Expand Down
Expand Up @@ -74,7 +74,7 @@ protected void GivenCompletedItem()
.Returns(new[] { targetDir });

Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
.Setup(c => c.GetFiles(targetDir, true))
.Returns(new[] { Path.Combine(targetDir, "somefile.flac") });

Mocker.GetMock<IDiskProvider>()
Expand Down
Expand Up @@ -9,6 +9,7 @@
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.TrackImport;
Expand Down Expand Up @@ -66,10 +67,26 @@ public void Setup()

private void GivenRootFolder(params string[] subfolders)
{
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.FolderExists(_rootFolder))
.Returns(true);

Mocker.GetMock<IDiskProvider>()
.Setup(s => s.GetDirectories(_rootFolder))
.Returns(subfolders);

Mocker.GetMock<IDiskProvider>()
.Setup(s => s.FolderEmpty(_rootFolder))
.Returns(subfolders.Empty());

FileSystem.AddDirectory(_rootFolder);

foreach (var folder in subfolders)
{
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.FolderExists(folder))
.Returns(true);

FileSystem.AddDirectory(folder);
}
}
Expand All @@ -79,7 +96,7 @@ private void GivenArtistFolder()
GivenRootFolder(_artist.Path);
}

private List<IFileInfo> GivenFiles(IEnumerable<string> files, DateTimeOffset? lastWrite = null)
private void GivenFiles(IEnumerable<string> files, DateTimeOffset? lastWrite = null)
{
if (lastWrite == null)
{
Expand All @@ -92,7 +109,9 @@ private List<IFileInfo> GivenFiles(IEnumerable<string> files, DateTimeOffset? la
FileSystem.AddFile(file, new MockFileData(string.Empty) { LastWriteTime = lastWrite.Value });
}

return files.Select(x => DiskProvider.GetFileInfo(x)).ToList();
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.GetFileInfos(It.IsAny<string>(), true))
.Returns(files.Select(x => DiskProvider.GetFileInfo(x)).ToList());
}

private void GivenKnownFiles(IEnumerable<string> files, DateTimeOffset? lastWrite = null)
Expand Down Expand Up @@ -139,7 +158,7 @@ public void should_not_scan_if_root_folder_is_empty()
ExceptionVerification.ExpectedWarns(1);

Mocker.GetMock<IDiskProvider>()
.Verify(v => v.GetFiles(_artist.Path, SearchOption.AllDirectories), Times.Never());
.Verify(v => v.GetFiles(_artist.Path, true), Times.Never());

Mocker.GetMock<IMediaFileTableCleanupService>()
.Verify(v => v.Clean(It.IsAny<string>(), It.IsAny<List<string>>()), Times.Never());
Expand Down Expand Up @@ -194,6 +213,9 @@ public void should_not_scan_extras_subfolder()

Subject.Scan(new List<string> { _artist.Path });

Mocker.GetMock<IDiskProvider>()
.Verify(v => v.GetFileInfos(It.IsAny<string>(), It.IsAny<bool>()), Times.Once());

Mocker.GetMock<IMakeImportDecision>()
.Verify(v => v.GetImportDecisions(It.Is<List<IFileInfo>>(l => l.Count == 1), It.IsAny<IdentificationOverrides>(), It.IsAny<ImportDecisionMakerInfo>(), It.IsAny<ImportDecisionMakerConfig>()), Times.Once());
}
Expand Down Expand Up @@ -384,6 +406,8 @@ private void GivenRejections()
[Test]
public void should_insert_new_unmatched_files_when_all_new()
{
GivenArtistFolder();

var files = new List<string>
{
Path.Combine(_artist.Path, "Season 1", "file1.flac"),
Expand All @@ -404,6 +428,8 @@ public void should_insert_new_unmatched_files_when_all_new()
[Test]
public void should_insert_new_unmatched_files_when_some_known()
{
GivenArtistFolder();

var files = new List<string>
{
Path.Combine(_artist.Path, "Season 1", "file1.flac"),
Expand All @@ -424,6 +450,8 @@ public void should_insert_new_unmatched_files_when_some_known()
[Test]
public void should_not_insert_files_when_all_known()
{
GivenArtistFolder();

var files = new List<string>
{
Path.Combine(_artist.Path, "Season 1", "file1.flac"),
Expand All @@ -448,6 +476,8 @@ public void should_not_insert_files_when_all_known()
[Test]
public void should_not_update_info_for_unchanged_known_files()
{
GivenArtistFolder();

var files = new List<string>
{
Path.Combine(_artist.Path, "Season 1", "file1.flac"),
Expand All @@ -472,6 +502,8 @@ public void should_not_update_info_for_unchanged_known_files()
[Test]
public void should_update_info_for_changed_known_files()
{
GivenArtistFolder();

var files = new List<string>
{
Path.Combine(_artist.Path, "Season 1", "file1.flac"),
Expand Down
Expand Up @@ -32,7 +32,7 @@ public void Setup()
};

Mocker.GetMock<IDiskProvider>()
.Setup(s => s.GetFileInfos(It.IsAny<string>(), It.IsAny<SearchOption>()))
.Setup(s => s.GetFileInfos(It.IsAny<string>(), It.IsAny<bool>()))
.Returns(new List<IFileInfo>());
}

Expand All @@ -51,7 +51,7 @@ private void GivenFiles(IEnumerable<string> files)
}

Mocker.GetMock<IDiskProvider>()
.Setup(s => s.GetFileInfos(It.IsAny<string>(), SearchOption.AllDirectories))
.Setup(s => s.GetFileInfos(It.IsAny<string>(), true))
.Returns(filesToReturn);
}

Expand All @@ -60,26 +60,26 @@ public void should_check_all_directories()
{
Subject.GetAudioFiles(_path);

Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, SearchOption.AllDirectories), Times.Once());
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, SearchOption.TopDirectoryOnly), Times.Never());
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, true), Times.Once());
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, false), Times.Never());
}

[Test]
public void should_check_all_directories_when_allDirectories_is_true()
{
Subject.GetAudioFiles(_path, true);

Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, SearchOption.AllDirectories), Times.Once());
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, SearchOption.TopDirectoryOnly), Times.Never());
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, true), Times.Once());
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, false), Times.Never());
}

[Test]
public void should_check_top_level_directory_only_when_allDirectories_is_false()
{
Subject.GetAudioFiles(_path, false);

Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, SearchOption.AllDirectories), Times.Never());
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, SearchOption.TopDirectoryOnly), Times.Once());
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, true), Times.Never());
Mocker.GetMock<IDiskProvider>().Verify(s => s.GetFileInfos(_path, false), Times.Once());
}

[Test]
Expand Down
@@ -1,5 +1,4 @@
using System;
using System.IO;
using System;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
Expand Down Expand Up @@ -42,7 +41,7 @@ public void Setup()
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetDirectories(RecycleBin))
.Returns(new[] { @"C:\Test\RecycleBin\Folder1", @"C:\Test\RecycleBin\Folder2", @"C:\Test\RecycleBin\Folder3" });

Mocker.GetMock<IDiskProvider>().Setup(s => s.GetFiles(RecycleBin, SearchOption.AllDirectories))
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetFiles(RecycleBin, true))
.Returns(new[] { @"C:\Test\RecycleBin\File1.avi", @"C:\Test\RecycleBin\File2.mkv" });
}

Expand Down

0 comments on commit 5fc1fc4

Please sign in to comment.