private static void FixUnityAssembliesStatusInDependencyGraph(AssemblyDependencyGraph dependencyGraph, IEnumerable <string> assemblyNames)
        {
            var unityAssemblies = assemblyNames.Where(an => an.StartsWith("UnityEngine") || an.StartsWith("UnityEditor"));

            foreach (var assemblyName in unityAssemblies)
            {
                var dep = dependencyGraph.FindAssembly(assemblyName);
                dep.Status |= AssemblyStatus.PublishesUpdaterConfigurations; // we know that those assemblies contains update configs
            }
        }
        /*
         * Given a list of assemblies, returns those that references assemblies contributing updater configurations
         * sorted by dependency (i.e, given assemblies, A, B & C such A -> B -> C, should return in C, B, A order)
         */
        private static IEnumerable <AssemblyUpdateCandidate> FindCandidatesForUpdatingSortedByDependency(IEnumerable <string> assemblyPaths, AssemblyDependencyGraph depGraph)
        {
            var candidates = new HashSet <AssemblyUpdateCandidate>();

            foreach (var assemblyPath in assemblyPaths)
            {
                var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);

                var depInfo = depGraph.FindAssembly(assemblyName);
                Debug.Assert(depInfo != null);

                // Any referenced assemblies contains updater configs?
                var referencedAssembliesWithUpdaterConfigs = depInfo.Dependencies.Where(a => (depGraph.FindAssembly(a.Name)?.Status & AssemblyStatus.PublishesUpdaterConfigurations) == AssemblyStatus.PublishesUpdaterConfigurations);
                if (referencedAssembliesWithUpdaterConfigs.Any())
                {
                    var isUnityExtension = assemblyPath.IsUnityExtension();
                    IEnumerable <string> updateConfigSources = new string[0];

                    // UnityExtensions should never use obsolete APIs (i.e, we should never need to update them)
                    if (!isUnityExtension)
                    {
                        updateConfigSources = ResolvePathOfAssembliesWithUpdaterConfigurations(referencedAssembliesWithUpdaterConfigs);
                    }

                    candidates.Add(new AssemblyUpdateCandidate
                    {
                        Name                = assemblyName,
                        Path                = assemblyPath,
                        DependencyGraph     = depInfo,
                        UpdateConfigSources = updateConfigSources
                    });
                }
            }

            // add the candidates sorted based on the dependency graph...
            var result = new List <AssemblyUpdateCandidate>();

            foreach (var assemblyName in depGraph.SortedDependents())
            {
                // We may have assemblies with the same name in different folders
                // (for example GUISystem/Standalone/UnityEngine.UI.dll & GUISystem/UnityEngine.UI.dll)
                var filteredCandidates = candidates.Where(c => CompareIgnoreCase(c.Name, assemblyName));
                result.AddRange(filteredCandidates);
            }

            return(result);
        }
        private static AssemblyUpdateCandidate CandidateForUpdatingFrom(string candidateAssemblyName, AssemblyDependencyGraph rootDepGraph)
        {
            string resolvedAssemblyPath = ResolveAssemblyPath(candidateAssemblyName);

            // this may happen if, for instance, after setting the dependency A -> B, *B* gets removed and *A* gets updated to a new version (we don't remove
            // the dependency from the graph.
            if (string.IsNullOrEmpty(resolvedAssemblyPath))
            {
                return(null);
            }

            var depGraph = rootDepGraph.FindAssembly(candidateAssemblyName);
            var referencesAssemblyWithUpdaterConfigs = depGraph.Dependencies.Where(depAssembly => (rootDepGraph.FindAssembly(depAssembly.Name)?.Status & AssemblyStatus.PublishesUpdaterConfigurations) == AssemblyStatus.PublishesUpdaterConfigurations);
            var updaterConfigSources = ResolvePathOfAssembliesWithUpdaterConfigurations(referencesAssemblyWithUpdaterConfigs);

            return(new AssemblyUpdateCandidate
            {
                Name = candidateAssemblyName,
                Path = resolvedAssemblyPath,
                DependencyGraph = depGraph,
                UpdateConfigSources = updaterConfigSources
            });
        }