aboutsummaryrefslogtreecommitdiff
path: root/src/Modules/MsBuildModuleExplorer.cs
blob: fa4592ec82f6c54120a6b8ba6a508ae1c96a14df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
    {
        ///<inheritdoc/>
        public IEnumerable<IProject> DiscoverProjects()
        {
            LinkedList<IProject> 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<FileInfo> 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<IProject> 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);
            }
        }
    }
}