diff --git a/src/ByteSync.Client/Services/Inventories/InventoryBuilder.cs b/src/ByteSync.Client/Services/Inventories/InventoryBuilder.cs index 948fbe4f..83e04c88 100644 --- a/src/ByteSync.Client/Services/Inventories/InventoryBuilder.cs +++ b/src/ByteSync.Client/Services/Inventories/InventoryBuilder.cs @@ -271,6 +271,7 @@ private void ProcessSubDirectories(InventoryPart inventoryPart, DirectoryInfo di if (IsReparsePoint(subDirectory)) { RecordSkippedEntry(inventoryPart, subDirectory, SkipReason.Symlink, FileSystemEntryKind.Symlink); + continue; } } @@ -377,57 +378,8 @@ private bool ShouldIgnoreHiddenDirectory(DirectoryInfo directoryInfo) { var isRoot = IsRootPath(inventoryPart, fileInfo); - var entryKind = PosixFileTypeClassifier.ClassifyPosixEntry(fileInfo.FullName); - if (entryKind == FileSystemEntryKind.Symlink) + if (TryHandleFileSkip(inventoryPart, fileInfo, isRoot)) { - RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.Symlink, FileSystemEntryKind.Symlink); - - return; - } - - if (IsPosixSpecialFile(entryKind)) - { - AddPosixSpecialFileAndLog(inventoryPart, fileInfo, entryKind); - - return; - } - - if (!isRoot && ShouldIgnoreHiddenFile(fileInfo)) - { - RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.Hidden, FileSystemEntryKind.RegularFile); - - return; - } - - if (!isRoot) - { - var systemSkipReason = GetSystemSkipReason(fileInfo); - if (systemSkipReason.HasValue) - { - RecordSkippedEntry(inventoryPart, fileInfo, systemSkipReason.Value, FileSystemEntryKind.RegularFile); - - return; - } - } - - if (IsReparsePoint(fileInfo)) - { - RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.Symlink, FileSystemEntryKind.Symlink); - - return; - } - - if (!FileSystemInspector.Exists(fileInfo)) - { - RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.NotFound); - - return; - } - - if (FileSystemInspector.IsOffline(fileInfo) || IsRecallOnDataAccess(fileInfo)) - { - RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.Offline, FileSystemEntryKind.RegularFile); - return; } @@ -454,6 +406,65 @@ private bool ShouldIgnoreHiddenDirectory(DirectoryInfo directoryInfo) } } + private bool TryHandleFileSkip(InventoryPart inventoryPart, FileInfo fileInfo, bool isRoot) + { + var entryKind = PosixFileTypeClassifier.ClassifyPosixEntry(fileInfo.FullName); + if (entryKind == FileSystemEntryKind.Symlink) + { + RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.Symlink, FileSystemEntryKind.Symlink); + + return true; + } + + if (IsPosixSpecialFile(entryKind)) + { + AddPosixSpecialFileAndLog(inventoryPart, fileInfo, entryKind); + + return true; + } + + if (!isRoot && ShouldIgnoreHiddenFile(fileInfo)) + { + RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.Hidden, FileSystemEntryKind.RegularFile); + + return true; + } + + if (!isRoot) + { + var systemSkipReason = GetSystemSkipReason(fileInfo); + if (systemSkipReason.HasValue) + { + RecordSkippedEntry(inventoryPart, fileInfo, systemSkipReason.Value, FileSystemEntryKind.RegularFile); + + return true; + } + } + + if (IsReparsePoint(fileInfo)) + { + RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.Symlink, FileSystemEntryKind.Symlink); + + return true; + } + + if (!FileSystemInspector.Exists(fileInfo)) + { + RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.NotFound); + + return true; + } + + if (FileSystemInspector.IsOffline(fileInfo) || IsRecallOnDataAccess(fileInfo)) + { + RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.Offline, FileSystemEntryKind.RegularFile); + + return true; + } + + return false; + } + private void DoAnalyze(InventoryPart inventoryPart, DirectoryInfo directoryInfo, CancellationToken cancellationToken) { @@ -480,6 +491,8 @@ private void DoAnalyze(InventoryPart inventoryPart, DirectoryInfo directoryInfo, if (IsPosixSpecialFile(entryKind)) { RecordSkippedEntry(inventoryPart, directoryInfo, SkipReason.SpecialPosixFile, entryKind); + _logger.LogWarning("Directory {Directory} is a POSIX special file ({EntryKind}) and will be skipped", + directoryInfo.FullName, entryKind); return; } @@ -610,13 +623,6 @@ private void AddInaccessibleFileAndLog(InventoryPart inventoryPart, FileInfo fil private void AddPosixSpecialFileAndLog(InventoryPart inventoryPart, FileInfo fileInfo, FileSystemEntryKind entryKind) { - inventoryPart.IsIncompleteDueToAccess = true; - var relativePath = BuildRelativePath(inventoryPart, fileInfo); - var fileDescription = new FileDescription(inventoryPart, relativePath) - { - IsAccessible = false - }; - AddFileSystemDescription(inventoryPart, fileDescription); RecordSkippedEntry(inventoryPart, fileInfo, SkipReason.SpecialPosixFile, entryKind); _logger.LogWarning("File {File} is a POSIX special file ({EntryKind}) and will be skipped", fileInfo.FullName, entryKind); } @@ -742,4 +748,4 @@ private void AddFileSystemDescription(InventoryPart inventoryPart, FileSystemDes } } } -} +} \ No newline at end of file diff --git a/tests/ByteSync.Client.IntegrationTests/Services/Inventories/TestInventoryBuilder.cs b/tests/ByteSync.Client.IntegrationTests/Services/Inventories/TestInventoryBuilder.cs index 854fafbb..90897655 100644 --- a/tests/ByteSync.Client.IntegrationTests/Services/Inventories/TestInventoryBuilder.cs +++ b/tests/ByteSync.Client.IntegrationTests/Services/Inventories/TestInventoryBuilder.cs @@ -747,7 +747,8 @@ public async Task Test_PosixFifo_IsSkipped() var sessionSettings = SessionSettings.BuildDefault(); var osPlatform = OperatingSystem.IsMacOS() ? OSPlatforms.MacOs : OSPlatforms.Linux; - inventoryBuilder = BuildInventoryBuilder(sessionSettings, null, null, osPlatform); + var inventoryProcessData = new InventoryProcessData(); + inventoryBuilder = BuildInventoryBuilder(sessionSettings, inventoryProcessData, null, osPlatform); inventoryBuilder.AddInventoryPart(sourceA.FullName); await inventoryBuilder.BuildBaseInventoryAsync(inventoryAFilePath); @@ -765,11 +766,11 @@ public async Task Test_PosixFifo_IsSkipped() inventory = inventoryBuilder.Inventory!; inventory.InventoryParts.Count.Should().Be(1); inventory.InventoryParts[0].DirectoryDescriptions.Count.Should().Be(0); - inventory.InventoryParts[0].FileDescriptions.Count.Should().Be(2); - - var fifoDescription = inventory.InventoryParts[0].FileDescriptions.Single(fd => fd.Name.Equals("pipeA")); - fifoDescription.IsAccessible.Should().BeFalse(); - inventory.InventoryParts[0].IsIncompleteDueToAccess.Should().BeTrue(); + inventory.InventoryParts[0].FileDescriptions.Count.Should().Be(1); + inventory.InventoryParts[0].FileDescriptions.Single().Name.Should().Be("fileA.txt"); + inventory.InventoryParts[0].IsIncompleteDueToAccess.Should().BeFalse(); + inventoryProcessData.SkippedEntries.Should() + .ContainSingle(entry => entry.Name == "pipeA" && entry.Reason == SkipReason.SpecialPosixFile); } [Test] diff --git a/tests/ByteSync.Client.UnitTests/Services/Inventories/InventoryBuilderInspectorTests.cs b/tests/ByteSync.Client.UnitTests/Services/Inventories/InventoryBuilderInspectorTests.cs index 9a2710b1..d6d7e941 100644 --- a/tests/ByteSync.Client.UnitTests/Services/Inventories/InventoryBuilderInspectorTests.cs +++ b/tests/ByteSync.Client.UnitTests/Services/Inventories/InventoryBuilderInspectorTests.cs @@ -339,7 +339,8 @@ public async Task Posix_Special_File_Is_Recorded() await builder.BuildBaseInventoryAsync(invPath); var part = builder.Inventory.InventoryParts.Single(); - part.FileDescriptions.Should().ContainSingle(fd => !fd.IsAccessible); + part.FileDescriptions.Should().BeEmpty(); + part.IsIncompleteDueToAccess.Should().BeFalse(); processData.SkippedEntries.Should() .ContainSingle(e => e.Name == "posix_special.txt" && e.Reason == SkipReason.SpecialPosixFile); } @@ -363,6 +364,28 @@ public async Task Posix_Symlink_Directory_Is_Recorded() processData.SkippedEntries.Should() .ContainSingle(e => e.Name == "root_posix_symlink" && e.Reason == SkipReason.Symlink); } + + [Test] + public async Task Posix_Special_Directory_Is_Recorded() + { + var insp = new Mock(MockBehavior.Strict); + var posix = new Mock(MockBehavior.Strict); + posix.Setup(p => p.ClassifyPosixEntry(It.IsAny())).Returns(FileSystemEntryKind.BlockDevice); + var (builder, processData) = CreateBuilderWithData(insp.Object, posix.Object); + + var root = Directory.CreateDirectory(Path.Combine(TestDirectory.FullName, "root_posix_special")); + + builder.AddInventoryPart(root.FullName); + var invPath = Path.Combine(TestDirectory.FullName, "inv_posix_special_dir.zip"); + await builder.BuildBaseInventoryAsync(invPath); + + var part = builder.Inventory.InventoryParts.Single(); + part.DirectoryDescriptions.Should().BeEmpty(); + part.FileDescriptions.Should().BeEmpty(); + part.IsIncompleteDueToAccess.Should().BeFalse(); + processData.SkippedEntries.Should() + .ContainSingle(e => e.Name == "root_posix_special" && e.Reason == SkipReason.SpecialPosixFile); + } [Test] public async Task Reparse_File_Is_Ignored()