private static int ProcessSuccessfulUpdates(AssemblyUpdaterUpdateTask[] tasks)
        {
            var assembliesToUpdate = GetAssembliesToBeUpdated();
            var succeededUpdates   = tasks.Where(t => t.Result == APIUpdaterAssemblyHelper.UpdatesApplied);

            if (!succeededUpdates.Any())
            {
                assembliesToUpdate.Clear();
                return(0);
            }

            if (AskForConsent(false) != APIUpdaterStatus.Accepted)
            {
                APIUpdaterLogger.WriteToFile(L10n.Tr("User declined to run APIUpdater"));
                return(0);
            }

            var assemblyPaths2 = succeededUpdates.Select(u => u.Candidate.Path).ToArray();

            APIUpdaterHelper.HandleFilesInPackagesVirtualFolder(assemblyPaths2);
            if (!APIUpdaterHelper.CheckReadOnlyFiles(assemblyPaths2))
            {
                return(0);
            }

            foreach (var succeedd in succeededUpdates)
            {
                APIUpdaterLogger.WriteToFile("{0}{1}", Environment.NewLine, succeedd.StdOut);
                FileUtil.MoveFileIfExists(succeedd.OutputPath, succeedd.Candidate.Path);
            }

            assembliesToUpdate.Clear();
            return(succeededUpdates.Count());
        }
        private static bool HandleAssemblyUpdaterErrors(IEnumerable <AssemblyUpdaterUpdateTask> allTasks)
        {
            var tasksWithErrors = allTasks.Where(t => APIUpdaterAssemblyHelper.IsError(t.Result) || t.Exception != null);

            if (!tasksWithErrors.Any())
            {
                return(false);
            }

            var sb = new StringBuilder(L10n.Tr("Unable to update following assemblies:"));

            foreach (var updaterTask in tasksWithErrors)
            {
                sb.AppendFormat("{1} (Name = {2}, Error = {3}) (Output: {4}){0}{5}{0}{6}{0}", Environment.NewLine, updaterTask.Candidate.Path, updaterTask.Candidate.Name, updaterTask.Result, updaterTask.OutputPath, updaterTask.StdOut, updaterTask.StdErr);
                if (updaterTask.Exception != null)
                {
                    sb.AppendFormat("\tException: {0}{1}", updaterTask.Exception, Environment.NewLine);
                }
            }

            ReportIgnoredAssembliesDueToPreviousErrors(sb, allTasks.Except(tasksWithErrors));

            APIUpdaterLogger.WriteErrorToConsole(sb.ToString());
            return(true);
        }
        private static void LogTimeoutError(AssemblyUpdaterCheckAssemblyPublishConfigsTask[] tasks, TimeSpan waitedTime)
        {
            var timedOut = tasks.Where(t => !t.Event.WaitOne(0));

            var sb = new StringBuilder(L10n.Tr("Timeout while checking assemblies:"));

            foreach (var task in timedOut)
            {
                sb.AppendFormat("{1}{0}", Environment.NewLine, task.Candidate.Path);
            }

            sb.AppendFormat(L10n.Tr("{0}Timeout: {1} ms"), Environment.NewLine, waitedTime.Milliseconds);
            sb.AppendFormat(L10n.Tr("{0}Update configurations from those assemblies may have not been applied."), Environment.NewLine);
            APIUpdaterLogger.WriteErrorToConsole(sb.ToString());
        }
        private static void LogTimeoutError(AssemblyUpdaterUpdateTask[] tasks)
        {
            var completedSuccessfully = tasks.Where(t => t.Event.WaitOne(0));
            var timedout = tasks.Where(t => !t.Event.WaitOne(0));

            var sb = new StringBuilder(L10n.Tr("Timeout while updating assemblies:"));

            foreach (var updaterTask in timedout)
            {
                sb.AppendFormat("{1} (Output: {2}){0}", Environment.NewLine, updaterTask.Candidate.Path, updaterTask.OutputPath);
            }

            ReportIgnoredAssembliesDueToPreviousErrors(sb, completedSuccessfully);

            APIUpdaterLogger.WriteErrorToConsole(sb.ToString());
        }
예제 #5
0
        internal static void UpdateAssemblies()
        {
            var assembliesToUpdate = GetAssembliesToBeUpdated();

            if (assembliesToUpdate.Count == 0)
            {
                return;
            }

            var assemblyPaths             = assembliesToUpdate.Select(c => c.Path);
            var anyAssemblyInAssetsFolder = assemblyPaths.Any(path => path.IndexOf("Assets/", StringComparison.OrdinalIgnoreCase) != -1);

            var sw           = Stopwatch.StartNew();
            var updatedCount = 0;

            var assembliesToCheckCount = assembliesToUpdate.Count;
            var tasks = assembliesToUpdate.Select(a => new AssemblyUpdaterUpdateTask(a)).ToArray();

            foreach (var task in tasks)
            {
                ThreadPool.QueueUserWorkItem(RunAssemblyUpdaterTask, task);
            }

            var finishOk   = false;
            var waitEvents = tasks.Select(t => t.Event).ToArray();
            var timeout    = TimeSpan.FromSeconds(30);

            if (WaitOnManyEvents(waitEvents, timeout))
            {
                if (!HandleAssemblyUpdaterErrors(tasks))
                {
                    updatedCount = ProcessSuccessfulUpdates(tasks);
                    finishOk     = updatedCount >= 0;
                }
            }
            else
            {
                LogTimeoutError(tasks);
            }

            sw.Stop();
            APIUpdaterLogger.WriteToFile(L10n.Tr("Update finished with {0} in {1} ms ({2}/{3} assembly(ies) updated)."), finishOk ? L10n.Tr("success") : L10n.Tr("error"), sw.ElapsedMilliseconds, updatedCount >= 0 ? updatedCount : 0, assembliesToCheckCount);

            PersistListOfAssembliesToUpdate();
        }
        private static string ResolveAssemblyPath(string assemblyName)
        {
            //find the assembly in Data/Managed or Data/Managed/UnityEngine
            var assemblyFileName    = assemblyName + ".dll";
            var managedPath         = GetUnityEditorManagedPath();
            var pathInManagedFolder = Path.Combine(managedPath, assemblyFileName);

            if (File.Exists(pathInManagedFolder))
            {
                return(pathInManagedFolder);
            }

            var pathInUnityEngineFolder = Path.Combine(Path.Combine(managedPath, "UnityEngine"), assemblyFileName);

            if (File.Exists(pathInUnityEngineFolder))
            {
                return(pathInUnityEngineFolder);
            }

            var assetsAssemblies = new HashSet <string>(AssetDatabase.GetAllAssetPaths().Where(assetPath => Path.GetExtension(assetPath) == ".dll").ToArray());

            // If the same assembly exist in multiple folders, choose the shortest path one. This ensures that for UnityExtensions we always pick the one at the root of
            // the extention folder.
            var resolvedList = assetsAssemblies.Where(a => CompareIgnoreCase(AssemblyNameFromPath(a), assemblyName)).ToArray();
            var assemblyPathInAssetsFolder = resolvedList.OrderBy(path => path.Length).FirstOrDefault();

            if (resolvedList.Length > 1 && !resolvedList.All(a => a.IsUnityExtension()))
            {
                APIUpdaterLogger.WriteToFile("Warning : Multiple matches found for assembly name '{0}'. Shortest path one ({1}) choosen as the source of updates. Full list: {2}", assemblyName, assemblyPathInAssetsFolder, string.Join(Environment.NewLine, resolvedList));
            }

            if (assemblyPathInAssetsFolder != null && (assemblyPathInAssetsFolder.IsInPackage() || assemblyPathInAssetsFolder.IsInAssetsFolder()))
            {
                return(assemblyPathInAssetsFolder);
            }

            //TODO: In order to support *pre-built* assemblies referencing assemblies (PA) built out of
            //      packages deployed as source code we need to find PA which is located in Library/ScriptAssemblies folder
            //      In this case, we need to look at the mono islands (editorComp.GetAllMonoIslands(EditorScriptCompilationOptions.BuildingForEditor))
            //      and consider the ones which have its source in packages:
            //      var isInPackage = i._files.Any(path => editorComp.IsPathInPackageDirectory(path));

            return(null);
        }
        private static AssemblyDependencyGraph ReadOrCreateAssemblyDependencyGraph(string assemblyDependencyGraphFilePath)
        {
            try
            {
                if (File.Exists(assemblyDependencyGraphFilePath))
                {
                    using (var stream = File.OpenRead(assemblyDependencyGraphFilePath))
                    {
                        return(AssemblyDependencyGraph.LoadFrom(stream));
                    }
                }
            }
            catch (IOException e)
            {
                APIUpdaterLogger.WriteToFile(string.Format(L10n.Tr("Failed to read assembly dependency graph ({0}). Exception: {1}")), assemblyDependencyGraphFilePath, e);
            }

            return(new AssemblyDependencyGraph());
        }
        internal static void ProcessImportedAssemblies(string[] assemblies)
        {
            var sw = Stopwatch.StartNew();

            var depGraph = UpdateDependencyGraph(assemblies);
            var sortedCandidatesForUpdating = FindCandidatesForUpdatingSortedByDependency(assemblies, depGraph);

            var assembliesToUpdate = GetAssembliesToBeUpdated();

            CollectImportedAssembliesToBeUpdated(assembliesToUpdate, sortedCandidatesForUpdating);
            UpdatePublishUpdaterConfigStatusAndAddDependents(assembliesToUpdate, sortedCandidatesForUpdating, depGraph);

            SaveDependencyGraph(depGraph, k_AssemblyDependencyGraphFilePath);

            sw.Stop();
            APIUpdaterLogger.WriteToFile(L10n.Tr("Processing imported assemblies took {0} ms ({1}/{2} assemblie(s))."), sw.ElapsedMilliseconds, assembliesToUpdate.Count, sortedCandidatesForUpdating.Count());

            UpdateAssemblies();
        }
        private static bool HandleCheckAssemblyPublishUpdaterConfigErrors(AssemblyUpdaterCheckAssemblyPublishConfigsTask[] nonTimedOutTasks)
        {
            var withErrors = nonTimedOutTasks.Where(t => APIUpdaterAssemblyHelper.IsError(t.Result) || t.Exception != null);

            if (!withErrors.Any())
            {
                return(false);
            }

            var sb = new StringBuilder(L10n.Tr("Failed to check following assemblies for updater configurations:\r\n"));

            foreach (var failledAssemblyInfo in withErrors)
            {
                sb.AppendFormat(L10n.Tr("{0} (ret = {1}):\r\n{2}\r\n{3}\r\n"), failledAssemblyInfo.Candidate.Path, failledAssemblyInfo.Result, failledAssemblyInfo.StdOut, failledAssemblyInfo.StdErr);
            }
            sb.Append("\r\n--------------");

            APIUpdaterLogger.WriteErrorToConsole(sb.ToString());

            return(true);
        }
        private static bool HandleAssemblyUpdaterErrors(IEnumerable <AssemblyUpdaterUpdateTask> allTasks)
        {
            var tasksWithErrors = allTasks.Where(t => APIUpdaterAssemblyHelper.IsError(t.Result) || APIUpdaterAssemblyHelper.IsUnknown(t.Result) || t.Exception != null);

            if (!tasksWithErrors.Any())
            {
                return(false);
            }

            var sb = new StringBuilder(L10n.Tr("Unable to update following assemblies:"));

            foreach (var updaterTask in tasksWithErrors)
            {
                sb.Append(FormatErrorFromTask(updaterTask));
            }

            ReportIgnoredAssembliesDueToPreviousErrors(sb, allTasks.Except(tasksWithErrors));

            APIUpdaterLogger.WriteErrorToConsole(sb.ToString());
            return(true);
        }
예제 #11
0
        private static string ResolveAssemblyPath(string assemblyName)
        {
            //find the assembly in Data/Managed or Data/Managed/UnityEngine
            var assemblyFileName    = assemblyName + ".dll";
            var managedPath         = GetUnityEditorManagedPath();
            var pathInManagedFolder = Path.Combine(managedPath, assemblyFileName);

            if (File.Exists(pathInManagedFolder))
            {
                return(pathInManagedFolder);
            }

            var pathInUnityEngineFolder = Path.Combine(Path.Combine(managedPath, "UnityEngine"), assemblyFileName);

            if (File.Exists(pathInUnityEngineFolder))
            {
                return(pathInUnityEngineFolder);
            }

            var assetsAssemblies = new HashSet <string>(AssetDatabase.GetAllAssetPaths().Where(assetPath => Path.GetExtension(assetPath) == ".dll").ToArray());

            // If the same assembly exist in multiple folders, choose the shortest path one.
            var resolvedList = assetsAssemblies.Where(a => CompareIgnoreCase(AssemblyNameFromPath(a), assemblyName)).ToArray();
            var assemblyPathInAssetsFolder = resolvedList.OrderBy(path => path.Length).FirstOrDefault();

            if (resolvedList.Length > 1)
            {
                APIUpdaterLogger.WriteToFile(L10n.Tr("Warning : Multiple matches found for assembly name '{0}'. Shortest path one ({1}) chosen as the source of updates. Full list: {2}"), assemblyName, assemblyPathInAssetsFolder, string.Join(Environment.NewLine, resolvedList));
            }

            if (assemblyPathInAssetsFolder != null && (assemblyPathInAssetsFolder.IsInPackage() || assemblyPathInAssetsFolder.IsInAssetsFolder()))
            {
                return(assemblyPathInAssetsFolder);
            }

            return(null);
        }
        private static void SaveDependencyGraph(AssemblyDependencyGraph dependencyGraph, string path)
        {
            try
            {
                var targetDir = Path.GetDirectoryName(path);
                if (!Directory.Exists(targetDir))
                {
                    Directory.CreateDirectory(targetDir);
                }

                using (var file = File.Open(path, System.IO.FileMode.Create))
                {
                    dependencyGraph.SaveTo(file);
                }
            }
            catch (UnauthorizedAccessException ex)
            {
                APIUpdaterLogger.WriteToFile(string.Format(L10n.Tr("Failed to save assembly dependency graph ({0}). Exception: {1}")), path, ex);
            }
            catch (IOException ex)
            {
                APIUpdaterLogger.WriteToFile(string.Format(L10n.Tr("Failed to save assembly dependency graph ({0}). Exception: {1}")), path, ex);
            }
        }
        internal static void UpdateAssemblies()
        {
            var assembliesToUpdate = GetAssembliesToBeUpdated();

            if (assembliesToUpdate.Count == 0)
            {
                return;
            }

            var assemblyPaths             = assembliesToUpdate.Select(c => c.Path);
            var anyAssemblyInAssetsFolder = assemblyPaths.Any(path => path.IndexOf("Assets/", StringComparison.OrdinalIgnoreCase) != -1);

            // Only try to connect to VCS if there are files under VCS that need to be updated
            if (anyAssemblyInAssetsFolder)
            {
                var failedToConnectToVcs = false;
                if (WaitForVCSServerConnection(true))
                {
                    failedToConnectToVcs = Provider.enabled && !APIUpdaterHelper.CheckoutAndValidateVCSFiles(assemblyPaths);
                }

                if (failedToConnectToVcs)
                {
                    assembliesToUpdate.Clear();
                    return;
                }
            }

            var sw           = Stopwatch.StartNew();
            var updatedCount = 0;

            var assembliesToCheckCount = assembliesToUpdate.Count;
            var tasks = assembliesToUpdate.Select(a => new AssemblyUpdaterUpdateTask(a)).ToArray();

            foreach (var task in tasks)
            {
                CollectAssemblyObsoleteAPIUsage(task.Candidate.Path);
                ThreadPool.QueueUserWorkItem(RunAssemblyUpdaterTask, task);
            }

            var finishOk   = false;
            var waitEvents = tasks.Select(t => t.Event).ToArray();
            var timeout    = TimeSpan.FromSeconds(30);

            if (WaitHandle.WaitAll(waitEvents, timeout))
            {
                if (!HandleAssemblyUpdaterErrors(tasks))
                {
                    updatedCount = ProcessSuccessfulUpdates(tasks);
                    finishOk     = true;
                }
            }
            else
            {
                LogTimeoutError(tasks);
            }

            sw.Stop();
            APIUpdaterLogger.WriteToFile(L10n.Tr("Update finished with {0} in {1} ms ({2}/{3} assemblie(s) updated)."), finishOk ? L10n.Tr("success") : L10n.Tr("error"), sw.ElapsedMilliseconds, updatedCount, assembliesToCheckCount);

            if (updatedCount > 0 && !EditorCompilationInterface.Instance.DoesProjectFolderHaveAnyScripts())
            {
                ReportPossibleUpdateFinished(false);
            }

            PersistListOfAssembliesToUpdate();
        }
예제 #14
0
        private static int ProcessSuccessfulUpdates(AssemblyUpdaterUpdateTask[] tasks)
        {
            var assembliesToUpdate = GetAssembliesToBeUpdated();
            var succeededUpdates   = tasks.Where(t => t.Result == APIUpdaterAssemblyHelper.UpdatesApplied);

            if (!succeededUpdates.Any())
            {
                assembliesToUpdate.Clear();
                return(0);
            }

            var assembliesRequiringConsent = FilterOutLocalAndEmbeddedPackagesWhenAskingForConsent(assembliesToUpdate.Select(a => a.Path)).ToArray();

            if (assembliesRequiringConsent.Length > 0 && !AskForConsent(assembliesRequiringConsent))
            {
                APIUpdaterLogger.WriteToFile(L10n.Tr("User declined to run APIUpdater"));
                return(0);
            }

            var updatedAssemblyPaths = succeededUpdates.Select(u => u.Candidate.Path).ToArray();

            if (!CheckoutFromVCSIfNeeded(updatedAssemblyPaths))
            {
                return(-1);
            }

            APIUpdaterHelper.HandleFilesInPackagesVirtualFolder(updatedAssemblyPaths);
            if (!APIUpdaterHelper.CheckReadOnlyFiles(updatedAssemblyPaths))
            {
                return(0);
            }

            foreach (var succeed in succeededUpdates)
            {
                APIUpdaterLogger.WriteToFile("{0}{1}", Environment.NewLine, succeed.StdOut);
                FileUtil.MoveFileIfExists(succeed.OutputPath, succeed.Candidate.Path);
            }

            assembliesToUpdate.Clear();
            return(succeededUpdates.Count());

            bool CheckoutFromVCSIfNeeded(string[] assemblyPathsToCheck)
            {
                // Only try to connect to VCS if there are files under VCS that need to be updated
                var assembliesInAssetsFolder = assemblyPathsToCheck.Where(path => path.IndexOf("Assets/", StringComparison.OrdinalIgnoreCase) != -1).ToArray();

                if (!assembliesInAssetsFolder.Any())
                {
                    return(true);
                }

                if (!WaitForVCSServerConnection())
                {
                    return(false);
                }

                var failedToCheckoutFiles = !APIUpdaterHelper.MakeEditable(assembliesInAssetsFolder);

                if (failedToCheckoutFiles)
                {
                    assembliesToUpdate.Clear();
                    return(false);
                }

                return(true);
            }

            IEnumerable <string> FilterOutLocalAndEmbeddedPackagesWhenAskingForConsent(IEnumerable <string> ass)
            {
                foreach (var path in ass.Select(path => path.Replace("\\", "/"))) // package manager paths are always separated by /
                {
                    var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(path);
                    if (packageInfo == null || packageInfo.source == PackageSource.Local || packageInfo.source == PackageSource.Embedded)
                    {
                        yield return(path);
                    }
                }
            }
        }