diff --git a/src/chocolatey/StringExtensions.cs b/src/chocolatey/StringExtensions.cs index 4b830da846..5da1455870 100644 --- a/src/chocolatey/StringExtensions.cs +++ b/src/chocolatey/StringExtensions.cs @@ -17,10 +17,15 @@ namespace chocolatey { using System; + using System.Collections.Generic; using System.Globalization; + using System.Linq; using System.Runtime.InteropServices; using System.Security; + using System.Text; using System.Text.RegularExpressions; + using System.Threading; + using System.Web.UI; using infrastructure.app; using infrastructure.logging; @@ -50,6 +55,81 @@ public static string FormatWith(this string input, params object[] formatting) } } + /// + /// Splits any Newline elements and ensures that each line is no longer than the configured . + /// Lines longer than the specified line length will be split on the last non-letter or digit before the max length. + /// + /// The input to split any lines on. + /// The line prefix used for all lines not being the first line. + /// Maximum length of the line. + /// The splitted formatted lines. + /// Not recommended to be used in hot paths. + public static string SplitOnSpace(this string input, string linePrefix = "", int maxLineLength = 70) + { + if (string.IsNullOrWhiteSpace(input)) + { + return string.Empty; + } + + var sb = new StringBuilder(input.Length); + var firstLine = true; + var stack = new Stack(input.Split('\n').Reverse()); + + while (stack.Count > 0) + { + var currentLine = stack.Pop(); + + if (currentLine.Length <= maxLineLength) + { + if (!firstLine && !string.IsNullOrEmpty(currentLine)) + { + sb.Append(linePrefix); + } + + sb.AppendLine(currentLine.TrimEnd()); + } + else + { + var index = 70 - 1; + + for (; index >= 0; index--) + { + if (char.IsWhiteSpace(currentLine[index]) || !char.IsLetterOrDigit(currentLine[index])) + { + break; + } + } + + if (index <= 0) + { + index = maxLineLength; + } + + if (!firstLine) + { + sb.Append(linePrefix); + } + + var subLine = currentLine.Substring(0, index); + sb.AppendLine(subLine.TrimEnd()); + + if (stack.Count > 0) + { + var nextLine = currentLine.Substring(index + 1).TrimStart() + stack.Pop(); + stack.Push(nextLine); + } + else + { + stack.Push(currentLine.Substring(index + 1).TrimStart()); + } + } + + firstLine = false; + } + + return sb.ToString(); + } + /// /// Performs a trim only if the item is not null /// diff --git a/src/chocolatey/infrastructure.app/validations/CacheFolderValidationLockdown.cs b/src/chocolatey/infrastructure.app/validations/CacheFolderValidationLockdown.cs index 653e603b57..17cf157a6b 100644 --- a/src/chocolatey/infrastructure.app/validations/CacheFolderValidationLockdown.cs +++ b/src/chocolatey/infrastructure.app/validations/CacheFolderValidationLockdown.cs @@ -78,7 +78,7 @@ public ICollection Validate(ChocolateyConfiguration config) result.Add(new ValidationResult { ExitCode = 0, - Message = "System Cache directory is not locked down to administrators. Remove the directory '{0}' to have Chocolatey CLI create it with the proper permissions.".FormatWith(cacheFolderPath), + Message = "System Cache directory is not locked down to administrators.\nRemove the directory '{0}' to have Chocolatey CLI create it with the proper permissions.".FormatWith(cacheFolderPath).SplitOnSpace(linePrefix: " "), Status = ValidationStatus.Warning }); } @@ -106,7 +106,7 @@ public ICollection Validate(ChocolateyConfiguration config) result.Add(new ValidationResult { ExitCode = 1, // Should we error? - Message = "System Cache directory was not created, or could not be locked down to administrators.", + Message = "System Cache directory was not created, or could not be locked down to administrators.".SplitOnSpace(linePrefix: " "), Status = ValidationStatus.Error }); }