diff --git a/source/Nuke.Tooling/ToolingExtensions.cs b/source/Nuke.Tooling/ToolingExtensions.cs index 44c8b8b9c..86ae0f568 100644 --- a/source/Nuke.Tooling/ToolingExtensions.cs +++ b/source/Nuke.Tooling/ToolingExtensions.cs @@ -6,7 +6,10 @@ using System.Linq; using JetBrains.Annotations; using Nuke.Common.IO; +using Nuke.Common.Utilities; using Nuke.Common.Utilities.Collections; +using Serilog; +using Serilog.Events; namespace Nuke.Common.Tooling; @@ -65,4 +68,13 @@ public static void Open(this AbsolutePath path) var verb = EnvironmentInfo.IsUnix ? "open" : path.DirectoryExists() ? "explorer.exe" : "call"; ProcessTasks.StartShell($"{verb} {path}"); } + + /// + /// Prints the content of a file using the specified . + /// + public static AbsolutePath Print(this AbsolutePath path, LogEventLevel level = LogEventLevel.Information) + { + Log.Write(level, "Content of {Path}".Append(Environment.NewLine).Append(path.ReadAllText()), path); + return path; + } } diff --git a/source/Nuke.Utilities/Collections/Enumerable.Random.cs b/source/Nuke.Utilities/Collections/Enumerable.Random.cs new file mode 100644 index 000000000..c38d28ae7 --- /dev/null +++ b/source/Nuke.Utilities/Collections/Enumerable.Random.cs @@ -0,0 +1,33 @@ +// Copyright 2023 Maintainers of NUKE. +// Distributed under the MIT License. +// https://github.com/nuke-build/nuke/blob/master/LICENSE + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Nuke.Common.Utilities.Collections; + +partial class EnumerableExtensions +{ + private static readonly Random s_randomNumberGenerator = new Random(); + + public static T Random(this IEnumerable collection) + { + var array = collection.ToArray(); + return array[s_randomNumberGenerator.Next(array.Length)]; + } + + public static ICollection Randomize(this ICollection collection) + { + var list = collection.ToList(); + var count = list.Count; + while (count > 1) { + count--; + var k = s_randomNumberGenerator.Next(count + 1); + (list[k], list[count]) = (list[count], list[k]); + } + + return list; + } +} diff --git a/source/Nuke.Utilities/Object.Apply.cs b/source/Nuke.Utilities/Object.Apply.cs new file mode 100644 index 000000000..ed5f1722e --- /dev/null +++ b/source/Nuke.Utilities/Object.Apply.cs @@ -0,0 +1,16 @@ +// Copyright 2023 Maintainers of NUKE. +// Distributed under the MIT License. +// https://github.com/nuke-build/nuke/blob/master/LICENSE + +using System; +using System.Linq; + +namespace Nuke.Common.Utilities; + +partial class ObjectExtensions +{ + public static TOutput Apply(this TInput input, Func transform) + { + return transform.Invoke(input); + } +} diff --git a/source/Nuke.Utilities/Task.WaitAll.cs b/source/Nuke.Utilities/Task.WaitAll.cs new file mode 100644 index 000000000..6ca6b3215 --- /dev/null +++ b/source/Nuke.Utilities/Task.WaitAll.cs @@ -0,0 +1,31 @@ +// Copyright 2023 Maintainers of NUKE. +// Distributed under the MIT License. +// https://github.com/nuke-build/nuke/blob/master/LICENSE + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Nuke.Common.Utilities; + +[PublicAPI] +[DebuggerNonUserCode] +[DebuggerStepThrough] +public static partial class TaskExtensions +{ + public static void WaitAll(this IEnumerable tasks) + { + var tasksArray = tasks.ToArray(); + Task.WaitAll(tasksArray); + } + + public static IReadOnlyCollection WaitAll(this IEnumerable> tasks) + { + var tasksArray = tasks.ToArray(); + Task.WaitAll(tasksArray); + return tasksArray.Select(x => x.Result).ToList(); + } +} diff --git a/source/Nuke.Utilities/Text/String.Truncate.cs b/source/Nuke.Utilities/Text/String.Truncate.cs new file mode 100644 index 000000000..c35207631 --- /dev/null +++ b/source/Nuke.Utilities/Text/String.Truncate.cs @@ -0,0 +1,16 @@ +// Copyright 2023 Maintainers of NUKE. +// Distributed under the MIT License. +// https://github.com/nuke-build/nuke/blob/master/LICENSE + +using System; +using System.Linq; + +namespace Nuke.Common.Utilities; + +partial class StringExtensions +{ + public static string Truncate(this string str, int maxChars) + { + return str.Length <= maxChars ? str : str.Substring(0, maxChars) + "…"; + } +} diff --git a/source/Nuke.Utilities/Url.WithUtmValues.cs b/source/Nuke.Utilities/Url.WithUtmValues.cs new file mode 100644 index 000000000..5748533b9 --- /dev/null +++ b/source/Nuke.Utilities/Url.WithUtmValues.cs @@ -0,0 +1,33 @@ +// Copyright 2023 Maintainers of NUKE. +// Distributed under the MIT License. +// https://github.com/nuke-build/nuke/blob/master/LICENSE + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using JetBrains.Annotations; + +namespace Nuke.Common.Utilities; + +[PublicAPI] +[DebuggerNonUserCode] +[DebuggerStepThrough] +public static class UrlExtensions +{ + public static Uri WithUtmValues(this Uri uri, string medium, string source, string campaign = null, string content = null) + { + var lastSegment = uri.Segments.Last().Trim('/').Apply(x => x.IsNullOrWhiteSpace() ? null : x); + + var dictionary = new Dictionary + { + ["utm_medium"] = medium.NotNullOrWhiteSpace(), + ["utm_source"] = source.NotNullOrWhiteSpace(), + ["utm_campaign"] = campaign ?? lastSegment, + ["utm_content"] = content ?? (campaign != null ? lastSegment : null), + }; + + var query = dictionary.Where(x => x.Value != null).Select(x => $"{x.Key}={x.Value}").Join("&"); + return new Uri(uri.AbsoluteUri + "?" + query); + } +}