示例#1
0
        /// <summary>
        /// Creates a new <see cref="SolutionDependencyContext"/>, possibly for a different subset of projects
        /// of the <see cref="Solutions"/> than the default set (all projects except build projects).
        /// </summary>
        /// <param name="m">The monitor to use.</param>
        /// <param name="traceGraphDetails">True to trace the details of the input and output (sorted) graphs.</param>
        /// <param name="projectFilter">
        /// Optional project filter.
        /// By default all projects are considered except build projects (see <see cref="Solution.BuildProject"/>).
        /// </param>
        /// <returns>The context or null on error.</returns>
        public SolutionDependencyContext CreateDependencyContext(IActivityMonitor m, bool traceGraphDetails, Func <IProject, bool> projectFilter = null)
        {
            if (projectFilter == null)
            {
                projectFilter = p => !p.IsBuildProject;
            }
            var sortables = new Dictionary <ISolution, SolutionItem>();

            foreach (var s in _solutions)
            {
                var sItem = new SolutionItem(s, s.Projects.Where(p => projectFilter(p)).Select(p => _projects[p]));
                sortables.Add(s, sItem);
            }

            var options = new DependencySorterOptions();

            if (traceGraphDetails)
            {
                options.HookInput  = i => i.Trace(m);
                options.HookOutput = i => i.Trace(m);
            }
            IDependencySorterResult result = DependencySorter.OrderItems(m, sortables.Values, null, options);

            if (!result.IsComplete)
            {
                result.LogError(m);
                return(new SolutionDependencyContext(this, result, GetBuildProjectInfo(m)));
            }
            // Building the list of SolutionDependencyContext.DependencyRow.
            var table = result.SortedItems
                        // 1 - Selects solutions along with their ordered index.
                        .Where(sorted => sorted.GroupForHead == null && sorted.Item is SolutionItem)
                        .Select(sorted =>
                                (
                                    Solution: (Solution)sorted.StartValue,
                                    // The projects from this solution that reference packages that are
                                    // produced by local solutions have a direct requires to a Package
                                    // that has a local Project.
                                    // 2 - First Map: LocalRefs is a set of value tuple (Project Origin, Package Target).
                                    LocalRefs: sorted.Children
                                    .Select(c => (SProject: c, Project: (Project)c.StartValue))
                                    .SelectMany(c => c.SProject.DirectRequires
                                                .Select(r => r.Item)
                                                .OfType <LocalPackageItem>()
                                                .Select(package => (Origin: c.Project, Target: package))
                                                )))
                        // 3 - Second Map: Expands the LocalRefs.
                        .SelectMany(s => s.LocalRefs.Any()
                                                ? s.LocalRefs.Select(r => new DependentSolution.Row
                                                                     (
                                                                         s.Solution,
                                                                         r.Origin,
                                                                         r.Target.Project
                                                                     ))
                                                : new[] { new DependentSolution.Row(s.Solution, null, null) }
                                    )
                        .ToList();

            // Now that the table of SolutionDependencyContext.DependencyRow is built, use it to compute the
            // pure solution dependency graph.
            //
            var       index        = new Dictionary <object, DependentSolution>();
            ISolution current      = null;
            var       depSolutions = new DependentSolution[sortables.Count];

            int idx = 0;

            foreach (var r in table)
            {
                if (current != r.Solution)
                {
                    current = r.Solution;
                    var newDependent = new DependentSolution(current, table, s => index[s]);
                    depSolutions[idx++] = newDependent;
                    index.Add(current.Name, newDependent);
                    index.Add(current, newDependent);
                }
            }
            Array.Sort(depSolutions, (d1, d2) =>
            {
                int cmp = d1.Rank - d2.Rank;
                if (cmp == 0)
                {
                    cmp = d1.Solution.Name.CompareTo(d2.Solution.Name);
                }
                return(cmp);
            });
            for (int i = 0; i < depSolutions.Length; ++i)
            {
                depSolutions[i].Index = i;
            }

            return(new SolutionDependencyContext(this, index, result, table, depSolutions, GetBuildProjectInfo(m)));
        }
示例#2
0
        /// <summary>
        /// Gets the information about build projects (see <see cref="Solution.BuildProject"/>)
        /// and their dependencies.
        /// </summary>
        /// <param name="m">The monitor to use.</param>
        /// <param name="traceGraphDetails">True to trace the details of the input and output (sorted) graphs.</param>
        /// <returns>The build projects information.</returns>
        BuildProjectsInfo GetBuildProjectInfo(IActivityMonitor m)
        {
            Debug.Assert(!_projects.PureProjectsMode);
            _projects.PureProjectsMode = true;
            try
            {
                using (m.OpenTrace($"Creating Build Projects information."))
                {
                    IDependencySorterResult rBuildProjects = DependencySorter.OrderItems(m, _projects.AllProjectItems.Where(p => p.Project.IsBuildProject), null);
                    if (!rBuildProjects.IsComplete)
                    {
                        rBuildProjects.LogError(m);
                        return(new BuildProjectsInfo(rBuildProjects, null));
                    }
                    else
                    {
                        var rankedProjects = rBuildProjects.SortedItems
                                             .Where(i => i.Item is ProjectItem)
                                             .Select(i => (i.Rank, ((ProjectItem)i.Item).Project,
                                                           DirectDeps: i.Requires
                                                           .Select(s => s.Item)
                                                           .OfType <ProjectItem>()
                                                           .Select(p => p.Project),
                                                           AllDeps: i.GetAllRequires()
                                                           .Select(s => s.Item)
                                                           .OfType <ProjectItem>()
                                                           .Select(p => p.Project)));

                        var zeroBuildProjects = rankedProjects.Select((p, idx) => new ZeroBuildProjectInfo(
                                                                          idx,
                                                                          p.Rank,
                                                                          p.Project,
                                                                          // UpgradePackages: Among direct dependencies, consider only the
                                                                          //                  published projects and the ones who are actually referenced
                                                                          //                  as a package (ignores ProjectReference).
                                                                          p.DirectDeps
                                                                          .Where(d => d.IsPublished &&
                                                                                 p.Project.PackageReferences.Any(r => d.GeneratedArtifacts
                                                                                                                 .Select(a => a.Artifact)
                                                                                                                 .Contains(r.Target.Artifact)))
                                                                          .ToArray(),
                                                                          // UpgradeZeroProjects: Among direct dependencies, consider all the
                                                                          //                      published projects, the ones who are actually referenced
                                                                          //                      as a package AND the ones that are ProjectReference.
                                                                          //                      ProjectReference MUST be transformed into PackageReference
                                                                          //                      during ZeroBuild.
                                                                          p.DirectDeps
                                                                          .Where(d => d.IsPublished)
                                                                          .ToArray(),

                                                                          // Dependencies: Considers all the projects.
                                                                          p.AllDeps.ToArray()

                                                                          ))
                                                .ToArray();

                        Debug.Assert(zeroBuildProjects.Select(z => z.Rank).IsSortedLarge());
                        Debug.Assert(zeroBuildProjects.Select(z => z.Index).IsSortedStrict());

                        return(new BuildProjectsInfo(rBuildProjects, zeroBuildProjects));
                    }
                }
            }
            finally
            {
                _projects.PureProjectsMode = false;
            }
        }