From 79d824cfb0e0cc9ff4fab0e0c546a83c0edaae1c Mon Sep 17 00:00:00 2001 From: vnugent Date: Tue, 7 May 2024 17:01:22 -0400 Subject: initial commit --- src/Extensions/FileManagerExtensions.cs | 135 ++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/Extensions/FileManagerExtensions.cs (limited to 'src/Extensions/FileManagerExtensions.cs') diff --git a/src/Extensions/FileManagerExtensions.cs b/src/Extensions/FileManagerExtensions.cs new file mode 100644 index 0000000..6f497e7 --- /dev/null +++ b/src/Extensions/FileManagerExtensions.cs @@ -0,0 +1,135 @@ +using System; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +using VNLib.Tools.Build.Executor.Model; +using VNLib.Tools.Build.Executor.Constants; +using static VNLib.Tools.Build.Executor.Constants.Config; + +namespace VNLib.Tools.Build.Executor.Extensions +{ + + internal static class FileManagerExtensions + { + + private static readonly ConditionalWeakTable _projectHashes = new(); + + /// + /// Gets all external dependencies for the current module + /// + /// + /// An array of project names of all the dependencies outside a given module + public static string[] GetExternalDependencies(this IModuleData module) + { + /* + * We need to get all child project dependencies that rely on projects + * outside of the current module. + * + * This assumes all projects within this model are properly linked + * and assumed to be build together, as is 99% of the case, otherwise + * custom build impl will happen at the Task level + */ + + //Get the project file names contained in the current module + string[] selfProjects = module.Projects.Select(static p => p.ProjectFile.Name).ToArray(); + + return module.Projects.SelectMany(static p => p.GetDependencies()).Where(dep => !selfProjects.Contains(dep)).ToArray(); + } + + /// + /// Determines if any source files have changed + /// + /// The most recent commit hash + public static async Task CheckSourceChangedAsync(this IModuleFileManager manager, IProject project, BuildConfig config, string commit) + { + //Compute current sum + string sum = await project.GetSourceFileHashAsync(config); + + //Old sum file exists + byte[]? sumData = await manager.ReadCheckSumAsync(project); + + //Try to read the old sum file + if (sumData != null) + { + //Parse sum file + using JsonDocument sumDoc = JsonDocument.Parse(sumData); + + //Get the sum + string? hexSum = sumDoc.RootElement.GetProperty("sum").GetString(); + + //Confirm the current sum and the found sum are equal + if (sum.Equals(hexSum, StringComparison.OrdinalIgnoreCase)) + { + Log.Verbose("Project {p} source is {up}", project.ProjectName, "up-to-date"); + + //Project source is up-to-date + project.UpToDate = true; + + //No changes made + return; + } + } + + Log.Verbose("Project {p} source is {up}", project.ProjectName, "changed"); + + //Store sum change + object sumChange = new Dictionary() + { + { "sum", sum }, + { "commit", commit }, + { "modified", DateTimeOffset.UtcNow.ToString("s") } + }; + + //Store sum change for later + _projectHashes.Add(project, sumChange); + + project.UpToDate = false; + } + + /// + /// Creates the module's output directory + /// + /// + public static void CreateOutput(this IModuleFileManager manager) + { + //Create output directory for solution + _ = Directory.CreateDirectory(manager.OutputDir); + } + + /// + /// Deletes the output's module directory + /// + /// + public static void CleanOutput(this IModuleFileManager manager) + { + //Delete output directory for solution + if (Directory.Exists(manager.OutputDir)) + { + Directory.Delete(manager.OutputDir, true); + } + } + + + /// + /// Writes the source file checksum change to the project's sum file + /// + /// + /// The project to write the checksum for + /// A task that resolves when the sum file has been updated + public static Task CommitSumChangeAsync(this IModuleFileManager manager, IProject project) + { + if (!_projectHashes.TryGetValue(project, out object? sumChange)) + { + return Task.CompletedTask; + } + + byte[] sumData = JsonSerializer.SerializeToUtf8Bytes(sumChange); + + return manager.WriteChecksumAsync(project, sumData); + } + } +} \ No newline at end of file -- cgit