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