From dd5f92021adee165d8bac00f2adf305482cd3b40 Mon Sep 17 00:00:00 2001 From: Gidado Mukhtar Balangoggo Date: Tue, 25 Aug 2026 17:19:17 +0100 Subject: [PATCH] fix: Add validation and error handling to ReplaceFileContents task fix: Add validation and error handling to ReplaceFileContents task - Validate source file exists before processing - Validate replacement file exists if specified - Add comprehensive error logging for file I/O failures - Handle edge cases in replacement key parsing - Detect and warn on duplicate replacement keys - Wrap file operations in try-catch to prevent silent failures This improves robustness by ensuring the task fails gracefully with clear error messages instead of leaving corrupted output files. Fixes task failures when source or replacement files are missing. --- build-tools/prep/ReplaceFileContents.cs | 108 +++++++++++++++++++----- 1 file changed, 86 insertions(+), 22 deletions(-) diff --git a/build-tools/prep/ReplaceFileContents.cs b/build-tools/prep/ReplaceFileContents.cs index 82e5717f..192b84bc 100644 --- a/build-tools/prep/ReplaceFileContents.cs +++ b/build-tools/prep/ReplaceFileContents.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -32,41 +32,105 @@ public override bool Execute () } } - if (File.Exists (DestinationFile.ItemSpec)) - File.Delete (DestinationFile.ItemSpec); + try + { + // Validate source file exists + if (!File.Exists (SourceFile.ItemSpec)) + { + Log.LogError ($"Source file not found: {SourceFile.ItemSpec}"); + return false; + } - string[] replacements; - if (!String.IsNullOrEmpty (ReplacementFilePath)) - replacements = File.ReadAllLines (ReplacementFilePath); - else - replacements = Replacements; - var r = GetReplacementInfo (replacements); - using (var i = File.OpenText (SourceFile.ItemSpec)) - using (var o = File.CreateText (DestinationFile.ItemSpec)) { - string line; - while ((line = i.ReadLine ()) != null) { - foreach (var e in r) { - line = line.Replace (e.Key, e.Value); + // Delete destination if it exists + if (File.Exists (DestinationFile.ItemSpec)) + { + try + { + File.Delete (DestinationFile.ItemSpec); + } + catch (Exception ex) + { + Log.LogError ($"Failed to delete destination file '{DestinationFile.ItemSpec}': {ex.Message}"); + return false; + } + } + + // Get replacement pairs + string[] replacements; + if (!String.IsNullOrEmpty (ReplacementFilePath)) + { + if (!File.Exists (ReplacementFilePath)) + { + Log.LogError ($"Replacement file not found: {ReplacementFilePath}"); + return false; + } + replacements = File.ReadAllLines (ReplacementFilePath); + } + else + { + replacements = Replacements; + } + + var r = GetReplacementInfo (replacements); + + // Process file with error handling + using (var i = File.OpenText (SourceFile.ItemSpec)) + using (var o = File.CreateText (DestinationFile.ItemSpec)) + { + string line; + while ((line = i.ReadLine ()) != null) + { + foreach (var e in r) + { + line = line.Replace (e.Key, e.Value); + } + o.WriteLine (line); } - o.WriteLine (line); } - } - return !Log.HasLoggedErrors; + return !Log.HasLoggedErrors; + } + catch (Exception ex) + { + Log.LogError ($"Task {nameof (ReplaceFileContents)} failed: {ex.Message}"); + return false; + } } static readonly char[] Separator = new [] { '=' }; static Dictionary GetReplacementInfo (string[] replacements) { - var r = new Dictionary (replacements?.Length ?? 0); - if (replacements == null) + var r = new Dictionary (replacements?.Length ?? 0); + if (replacements == null || replacements.Length == 0) return r; - foreach (var e in replacements) { + + foreach (var e in replacements) + { if (string.IsNullOrEmpty (e)) continue; + var kvp = e.Split (Separator, 2, StringSplitOptions.RemoveEmptyEntries); - r.Add (kvp [0], kvp.Length > 1 ? kvp [1] : ""); + + // Validate we have a key + if (kvp.Length == 0) + { + continue; // Skip malformed lines + } + + string key = kvp[0]; + string value = kvp.Length > 1 ? kvp[1] : ""; + + // Warn if key already exists (duplicate replacement) + if (r.ContainsKey (key)) + { + Log.LogWarning ($"Duplicate replacement key: '{key}'"); + r[key] = value; // Override with latest + } + else + { + r.Add (key, value); + } } return r; }