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); }
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); }