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 18, 2023
1 parent 03c93c9 commit 331d0c9
Show file tree
Hide file tree
Showing 28 changed files with 111 additions and 78 deletions.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Books;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.MediaFiles;
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 GivenAuthorFolder()
GivenRootFolder(_author.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(_author.Path, SearchOption.AllDirectories), Times.Never());
.Verify(v => v.GetFiles(_author.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> { _author.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()
{
GivenAuthorFolder();

var files = new List<string>
{
Path.Combine(_author.Path, "Season 1", "file1.mobi"),
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()
{
GivenAuthorFolder();

var files = new List<string>
{
Path.Combine(_author.Path, "Season 1", "file1.mobi"),
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()
{
GivenAuthorFolder();

var files = new List<string>
{
Path.Combine(_author.Path, "Season 1", "file1.mobi"),
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()
{
GivenAuthorFolder();

var files = new List<string>
{
Path.Combine(_author.Path, "Season 1", "file1.mobi"),
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()
{
GivenAuthorFolder();

var files = new List<string>
{
Path.Combine(_author.Path, "Season 1", "file1.mobi"),
Expand Down
Original file line number Diff line number Diff line change
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.GetBookFiles(_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.GetBookFiles(_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.GetBookFiles(_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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.IO;
using System;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
Expand Down Expand Up @@ -68,7 +67,7 @@ public void should_call_fileSetLastWriteTime_for_each_file()
WithRecycleBin();
var path = @"C:\Test\TV\30 Rock".AsOsAgnostic();

Mocker.GetMock<IDiskProvider>().Setup(s => s.GetFiles(@"C:\Test\Recycle Bin\30 Rock".AsOsAgnostic(), SearchOption.AllDirectories))
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetFiles(@"C:\Test\Recycle Bin\30 Rock".AsOsAgnostic(), true))
.Returns(new[] { "File1", "File2", "File3" });

Mocker.Resolve<RecycleBinProvider>().DeleteFolder(path);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.IO;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
Expand All @@ -22,7 +21,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.TopDirectoryOnly))
Mocker.GetMock<IDiskProvider>().Setup(s => s.GetFiles(RecycleBin, false))
.Returns(new[] { @"C:\Test\RecycleBin\File1.avi", @"C:\Test\RecycleBin\File2.mkv" });
}

Expand Down

0 comments on commit 331d0c9

Please sign in to comment.