From 10cef292e71c98499c214f2a23de8e16edf51c31 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 31 Oct 2026 23:24:49 +0000 Subject: [PATCH 1/3] Skip Finder's Icon\r folder-icon file instead of failing it [patch] Finder writes an empty "Icon\r" file when a folder gets a custom icon. It was decoded as an input, failed, and made an otherwise clean batch exit 2. IsFileManagerMetadata now skips it alongside .DS_Store and desktop.ini. Fixes ktsu-dev/IconHelper#163 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017vfJW4hvLssY2rDFbS3wDM --- IconHelper.Test/ProcessDirectoryTests.cs | 31 ++++++++++++++++++++++++ IconHelper/IconHelper.cs | 9 ++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/IconHelper.Test/ProcessDirectoryTests.cs b/IconHelper.Test/ProcessDirectoryTests.cs index 9a7ddf3..7f017c9 100644 --- a/IconHelper.Test/ProcessDirectoryTests.cs +++ b/IconHelper.Test/ProcessDirectoryTests.cs @@ -187,6 +187,37 @@ public void SkipsFileManagerMetadataWithoutCountingItAsFailed() Assert.AreEqual(1, Directory.GetFiles(output).Length); } + [TestMethod] + public void TreatsFindersCustomFolderIconFileAsMetadata() + { + Assert.IsTrue(IconHelper.IsFileManagerMetadata("Icon\r"), "Finder's custom folder icon file is metadata, not an icon."); + Assert.IsFalse(IconHelper.IsFileManagerMetadata("Icon"), "Only the CR-suffixed name is Finder's; a plain Icon file is still an input."); + Assert.IsFalse(IconHelper.IsFileManagerMetadata("icon\r"), "Finder always writes the name with a capital I."); + } + + [TestMethod] + public void SkipsFindersCustomFolderIconFileWithoutCountingItAsFailed() + { + // Windows can't create a file name containing a carriage return, and a folder that held one + // would not reach the tool there anyway, so the batch-level check runs on Linux and macOS. + if (OperatingSystem.IsWindows()) + { + Assert.Inconclusive("Windows cannot create a file named \"Icon\\r\"."); + } + + using TempDirectory temp = new(); + string input = temp.Combine("in"); + string output = temp.Combine("out"); + Directory.CreateDirectory(input); + File.WriteAllBytes(Path.Join(input, "Icon\r"), []); + WritePng(Path.Join(input, "star.png"), 64); + + BatchResult result = IconHelper.ProcessDirectory(ArgumentsFor(input, output), NamedColors.White); + + Assert.AreEqual(new BatchResult(1, 0), result, "Finder's Icon\\r file should be neither written nor failed."); + Assert.AreEqual(IconHelper.ExitSuccess, IconHelper.ExitCodeFor(result)); + } + [TestMethod] public void ReportsAndSkipsAFileThatCannotBeOpened() { diff --git a/IconHelper/IconHelper.cs b/IconHelper/IconHelper.cs index eceabea..8725059 100644 --- a/IconHelper/IconHelper.cs +++ b/IconHelper/IconHelper.cs @@ -190,12 +190,15 @@ internal static BatchResult ProcessDirectory(Arguments args, Color color) /// /// Names that Finder and Explorer drop into any folder they open: dot-files such as .DS_Store and - /// ._ AppleDouble files, plus Thumbs.db, ehthumbs.db and desktop.ini. They are not icons, so they - /// count as neither written nor failed; counting them as failures made every batch on such a - /// folder exit 2 and taught scripts to ignore the code that reports real decode failures. + /// ._ AppleDouble files, plus Thumbs.db, ehthumbs.db and desktop.ini, and the "Icon\r" file Finder + /// writes when a folder is given a custom icon (its data fork is empty; the icon lives in the + /// resource fork). They are not icons, so they count as neither written nor failed; counting them + /// as failures made every batch on such a folder exit 2 and taught scripts to ignore the code that + /// reports real decode failures. /// internal static bool IsFileManagerMetadata(string fileName) => fileName.StartsWith('.') + || fileName.Equals("Icon\r", StringComparison.Ordinal) || fileName.Equals("Thumbs.db", StringComparison.OrdinalIgnoreCase) || fileName.Equals("ehthumbs.db", StringComparison.OrdinalIgnoreCase) || fileName.Equals("desktop.ini", StringComparison.OrdinalIgnoreCase); From cfbac1c1ee4fd39271e8e3cc311c8a018d23e7c6 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 31 Oct 2026 23:31:45 +0000 Subject: [PATCH 2/3] Bump SixLabors.ImageSharp to 3.2.0 so restore passes NU1903 3.1.12 carries GHSA-v76p-62qx-wwq2, and NuGet audit warnings are errors, so restore fails on main and on every PR. Ported from #145. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017vfJW4hvLssY2rDFbS3wDM --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 3e701c9..f94954b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ - + From c27076177a05f11f207af4eb090f3eb6d4edd037 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 31 Oct 2026 23:33:17 +0000 Subject: [PATCH 3/3] Revert the ImageSharp 3.2.0 bump: 3.2.0 fails CI without a Six Labors license 3.2.0 is the only release that fixes GHSA-v76p-62qx-wwq2, but its build targets fail any CI build that has no SixLaborsLicenseKey. Picking a license, an audit suppression or another library is a maintainer decision, so this PR goes back to main's dependency set. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017vfJW4hvLssY2rDFbS3wDM --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index f94954b..3e701c9 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ - +