diff --git a/API.Tests/Services/DirectoryServiceTests.cs b/API.Tests/Services/DirectoryServiceTests.cs index 62ace504f..95470db1a 100644 --- a/API.Tests/Services/DirectoryServiceTests.cs +++ b/API.Tests/Services/DirectoryServiceTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.IO.Abstractions; @@ -373,6 +373,29 @@ namespace API.Tests.Services } #endregion + #region IsDirectoryEmpty + [Fact] + public void IsDirectoryEmpty_DirectoryIsEmpty() + { + const string testDirectory = "c:/manga/"; + var fileSystem = new MockFileSystem(); + var ds = new DirectoryService(Substitute.For>(), fileSystem); + + Assert.False(ds.IsDirectoryEmpty("c:/manga/")); + } + + [Fact] + public void IsDirectoryEmpty_DirectoryIsNotEmpty() + { + const string testDirectory = "c:/manga/"; + var fileSystem = new MockFileSystem(); + fileSystem.AddFile($"{testDirectory}data-0.txt", new MockFileData("abc")); + var ds = new DirectoryService(Substitute.For>(), fileSystem); + + Assert.False(ds.IsDirectoryEmpty("c:/manga/")); + } + #endregion + #region ExistOrCreate [Fact] public void ExistOrCreate_ShouldCreate() diff --git a/API/Services/DirectoryService.cs b/API/Services/DirectoryService.cs index 80bb9ee92..40fa61285 100644 --- a/API/Services/DirectoryService.cs +++ b/API/Services/DirectoryService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; @@ -32,6 +32,7 @@ namespace API.Services void CopyFileToDirectory(string fullFilePath, string targetDirectory); int TraverseTreeParallelForEach(string root, Action action, string searchPattern, ILogger logger); bool IsDriveMounted(string path); + bool IsDirectoryEmpty(string path); long GetTotalSize(IEnumerable paths); void ClearDirectory(string directoryPath); void ClearAndDeleteDirectory(string directoryPath); @@ -259,7 +260,18 @@ namespace API.Services return FileSystem.DirectoryInfo.FromDirectoryName(FileSystem.Path.GetPathRoot(path) ?? string.Empty).Exists; } - public string[] GetFilesWithExtension(string path, string searchPatternExpression = "") + + /// + /// Checks if the root path of a path is empty or not. + /// + /// + /// + public bool IsDirectoryEmpty(string path) + { + return Directory.EnumerateFileSystemEntries(path).Any(); + } + + public string[] GetFilesWithExtension(string path, string searchPatternExpression = "") { // TODO: Use GitFiles instead if (searchPatternExpression != string.Empty) diff --git a/API/Services/Tasks/ScannerService.cs b/API/Services/Tasks/ScannerService.cs index 46eee0ff6..4d3679e97 100644 --- a/API/Services/Tasks/ScannerService.cs +++ b/API/Services/Tasks/ScannerService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -221,6 +221,13 @@ public class ScannerService : IScannerService return; } + // For Docker instances check if any of the folder roots are not available (ie disconnected volumes, etc) and fail if any of them are + if (library.Folders.Any(f => !_directoryService.IsDirectoryEmpty(f.Path))) + { + _logger.LogError("Some of the root folders for the library are empty. Either your mount has been disconnected or you are trying to delete all series in the library. Scan will be aborted. Check that your mount is connected or change the library's root folder and rescan."); + return; + } + _logger.LogInformation("[ScannerService] Beginning file scan on {LibraryName}", library.Name); await _messageHub.Clients.All.SendAsync(SignalREvents.ScanLibraryProgress, MessageFactory.ScanLibraryProgressEvent(libraryId, 0));