using System; using System.IO; using System.Linq; using System.Collections.Generic; using Microsoft.Build.Construction; using VNLib.Tools.Build.Executor.Model; using VNLib.Tools.Build.Executor.Projects; using VNLib.Tools.Build.Executor.Constants; using static VNLib.Tools.Build.Executor.Constants.Config; using VNLib.Tools.Build.Executor.Extensions; namespace VNLib.Tools.Build.Executor.Modules { /* * Discovers all projects within a dotnet solution file. First it finds the solution file in the * working directory, then it parses the solution file to find all projects within the solution. * * Leaf projects are then discovered by searching for all project files within the working directory * that are not part of the solution. */ internal sealed class MsBuildModuleExplorer(BuildConfig config, IModuleData Module, DirectoryInfo ModuleDir) : IProjectExplorer { /// public IEnumerable DiscoverProjects() { LinkedList projects = new(); //First load the solution file FileInfo? slnFile = ModuleDir.EnumerateFiles("*.sln", SearchOption.TopDirectoryOnly).FirstOrDefault(); if(slnFile is not null) { GetProjectsForSoution(slnFile, projects); } //Capture any leaf projects that are not part of the solution IEnumerable leafProjects = ModuleDir.EnumerateFiles("package.json", SearchOption.AllDirectories).Distinct(); //Capture them foreach (FileInfo leafProjFile in leafProjects) { //Create relative file path string realtivePath = leafProjFile.FullName.Replace(ModuleDir.FullName, string.Empty).TrimStart(Path.DirectorySeparatorChar); //If the leaf project is ignored, skip it if (Module.Repository.IsFileIgnored(realtivePath)) { continue; } //Create the leaf project LeafProject project = new(config, leafProjFile); Log.Verbose("Discovered leaf project in {proj} ", leafProjFile.DirectoryName); projects.AddLast(project); } return projects; } private static void GetProjectsForSoution(FileInfo slnFile, LinkedList projects) { //Parse solution SolutionFile Solution = SolutionFile.Parse(slnFile.FullName); //Loop through all artificats within the solution foreach (ProjectInSolution proj in Solution.ProjectsInOrder.Where(static p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)) { //Ignore test projects in a solution if(proj.ProjectName.Contains("test", StringComparison.OrdinalIgnoreCase)) { continue; } //Create the new project artifact DotnetProject project = new(new(proj.AbsolutePath), proj.ProjectName); Log.Verbose("Discovered project {proj} ", proj.ProjectName); projects.AddLast(project); } } } }