From d1955932cdb87068240ea35d9e23cdb1f08b5158 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 09:27:44 +0000 Subject: [PATCH] Name the full path of a file that fails to hash [patch] FileHasher.ReportSkipped printed only the file name, so in a tree where IMG_0001.jpg or index.js repeats there was no way to tell which copy could not be read. It now prints the absolute path, like every other diagnostic the tool writes. Fixes #154 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Q5ZFyLG9PgeKn5RpzhWEUQ --- FileDeduplicator.Test/VerbOutputTests.cs | 20 ++++++++++++++++++++ FileDeduplicator/FileHasher.cs | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/FileDeduplicator.Test/VerbOutputTests.cs b/FileDeduplicator.Test/VerbOutputTests.cs index f650ade..ad6db6e 100644 --- a/FileDeduplicator.Test/VerbOutputTests.cs +++ b/FileDeduplicator.Test/VerbOutputTests.cs @@ -152,6 +152,26 @@ public void StatsReportsAFileItCannotHashAsUnreadable() Assert.Contains("Duplicate groups: 0", output); } + /// + /// A file that cannot be hashed is named by its full path, so the failing copy can be found + /// among others sharing its file name. + /// + [TestMethod] + public void AHashingErrorNamesTheFullPath() + { + // Arrange + using TempTree tree = new(); + _ = tree.Write("one/IMG_0001.jpg", "alpha"); + AbsoluteFilePath locked = tree.Write("two/IMG_0001.jpg", "beta"); + using FileStream holder = new(locked.WeakString, FileMode.Open, FileAccess.ReadWrite, FileShare.None); + + // Act + string output = ConsoleCapture.Run(new Stats { PathString = tree.Root.WeakString }); + + // Assert + Assert.Contains($"Error hashing {locked}:", output); + } + /// /// A tree where every file hashes has no unreadable line at all. /// diff --git a/FileDeduplicator/FileHasher.cs b/FileDeduplicator/FileHasher.cs index bfb5ff0..84b5ce9 100644 --- a/FileDeduplicator/FileHasher.cs +++ b/FileDeduplicator/FileHasher.cs @@ -51,7 +51,9 @@ private static void ReportSkipped(AbsoluteFilePath filePath, Exception ex) { lock (ConsoleLock) { - Console.WriteLine($" Error hashing {filePath.FileName}: {ex.Message}"); + // The full path, not the file name: index.js or IMG_0001.jpg can repeat dozens of times in + // one tree, and this line is the only place the failing copy is ever named. + Console.WriteLine($" Error hashing {filePath}: {ex.Message}"); } }