internal static (Dictionary <string, string> ColoringDictionary, Dictionary <string, SortedSet <string> > UniqueProjectsForDependency) Walk(string targetProject, IDictionary <string, SortedSet <string> > dependencyGraph)
        {
            // We are going to need to perform this for every direct dependency of the target project
            if (!dependencyGraph.ContainsKey(targetProject))
            {
                string exception = $"Could not find project `{targetProject}` in given dictionary.";
                throw new NotSupportedException(exception);
            }

            // If we do not have enough colors to represent all N-Order Dependencies we need to throw
            if (dependencyGraph[targetProject].Count > ColorScheme.Length)
            {
                string exception = $"There are not enough colors to properly render the graph. Need {dependencyGraph[targetProject].Count}; only have {ColorScheme.Length}";
                throw new NotSupportedException(exception);
            }

            Dictionary <string, string> coloringDictionary = new Dictionary <string, string>();
            Dictionary <string, SortedSet <string> > uniqueDependenciesForProject = new Dictionary <string, SortedSet <string> >();

            // Load the Initial Dependencies into the Color Dictionary
            string[] directDependencyProjects = dependencyGraph[targetProject].ToArray();
            for (int i = 0; i < directDependencyProjects.Length; i++)
            {
                coloringDictionary.Add(directDependencyProjects[i], ColorScheme[i]);
            }

            SortedSet <string> directDependenciesOfTargetProject = dependencyGraph[targetProject];

            foreach (string dependencyOfTargetProject in directDependenciesOfTargetProject)
            {
                // We need to remove the direct dependency from the existing
                // graph to determine what the remaining N-Order Dependencies
                // of the target project are. To do this we need a DEEP COPY
                // CLONE of the Original Dependency Graph. DO NOT USE THE
                // OVERLOAD WHICH IS ONLY A SHALLOW COPY!
                IDictionary <string, SortedSet <string> > modifiedDependencyGraph = CloneDependencyGraph(dependencyGraph);
                modifiedDependencyGraph[targetProject].Remove(dependencyOfTargetProject);
                HashSet <string> modifiedDependencies = IdentifyRequiredProjects.GenerateNOrderDependencies(targetProject, modifiedDependencyGraph);

                // Now using the original dependency graph get the N-Order
                // Dependencies of the current dependency
                HashSet <string> directDependencyDependencies = IdentifyRequiredProjects.GenerateNOrderDependencies(dependencyOfTargetProject, dependencyGraph);

                // Now if there are any dependencies that are ONLY dependencies
                // of the current dependency then those would "fall away" if we
                // trimmed out the reference.
                string[] distinctDependenciesOfCurrentDependency = directDependencyDependencies.Except(modifiedDependencies).ToArray();

                // Save this information
                uniqueDependenciesForProject.Add(dependencyOfTargetProject, new SortedSet <string>(distinctDependenciesOfCurrentDependency));

                // Update the coloring information as well
                foreach (string dependency in distinctDependenciesOfCurrentDependency)
                {
                    coloringDictionary.Add(dependency, coloringDictionary[dependencyOfTargetProject]);
                }
            }

            return(coloringDictionary, uniqueDependenciesForProject);
        }
Пример #2
0
        static void Main(string[] args)
        {
            if (!args.Any())
            {
                Console.WriteLine("You did not provide the required targetProject argument.");
                Environment.Exit(1);
            }

            // Get the DotGraph File
            string dotGraphFile = args.FirstOrDefault();

            // See if the target project flag has been set
            string targetProject = _ParseForTargetProjectFlag(args);

            if (string.IsNullOrWhiteSpace(dotGraphFile) || !File.Exists(dotGraphFile))
            {
                string missingDotGraphFile = "The Provided DotGraph Argument was not valid. This tool requires a valid DotGraph File.";
                Console.WriteLine(missingDotGraphFile);
                Environment.Exit(1);
            }

            if (string.IsNullOrWhiteSpace(targetProject))
            {
                string missingTargetProject = "You must provide a `-TargetProject` to this tool.";
                Console.WriteLine(missingTargetProject);
                Environment.Exit(1);
            }

            ProcessOperation operation = _ParseForOperation(args);

            IDictionary <string, SortedSet <string> > loadedGraph = DotGraph.LoadDependencyGraph(dotGraphFile);

            string consoleOutput = string.Empty;

            switch (operation)
            {
            case ProcessOperation.Default:
            case ProcessOperation.IdentifyRequiredProjects:
            {
                consoleOutput = IdentifyRequiredProjects.Execute(targetProject, loadedGraph);
                break;
            }

            case ProcessOperation.IdentifyAffectedProjects:
            {
                consoleOutput = IdentifyAffectedProjects.Execute(targetProject, loadedGraph);
                break;
            }

            case ProcessOperation.IdentifyDirectDependencyCounts:
            {
                consoleOutput = IdentifyDirectDependencyCounts.Execute(targetProject, loadedGraph);
                break;
            }

            default:
            {
                Console.WriteLine($"Unknown Operation {operation.ToString()}");
                Environment.Exit(1);
                break;
            }
            }

            Console.WriteLine(consoleOutput);
        }