static IReadOnlyList <IPluginInfo> MakePluginInfoList( IPluginsIndex index, ImmutableArray <IPluginManifest> installedPluginsManifests, Telemetry.ITelemetryCollector telemetryCollector ) { Dictionary <string, PluginInfo> map = new Dictionary <string, PluginInfo>(); var installedPluginsMap = installedPluginsManifests.ToLookup(p => p.Id); foreach (var indexedPlugin in index.Plugins) { map[indexedPlugin.Id] = new PluginInfo { id = indexedPlugin.Id, version = indexedPlugin.Version, name = indexedPlugin.Name, description = indexedPlugin.Description, indexItem = indexedPlugin, installedPluginManifest = installedPluginsMap[indexedPlugin.Id].FirstOrDefault(), dependenciesIds = indexedPlugin.Dependencies, }; } installedPluginsManifests .Where(installedPlugin => !map.ContainsKey(installedPlugin.Id)) .Select(installedPlugin => new PluginInfo { id = installedPlugin.Id, version = installedPlugin.Version, name = installedPlugin.Name, description = installedPlugin.Description, indexItem = null, installedPluginManifest = installedPlugin, dependenciesIds = installedPlugin.Dependencies }) .ToList() .ForEach(p => map[p.id] = p); foreach (var p in map.Values.ToArray()) { var deps = p.dependenciesIds.Select(depId => { bool resolved = map.TryGetValue(depId, out var dep); return(resolved, depId, dep); }).ToArray(); var unresolvedDeps = deps.Where(d => !d.resolved).Select(d => d.depId).ToArray(); if (unresolvedDeps.Length > 0) { telemetryCollector.ReportException(new Exception("Bad plug-ins index"), $"Plug-in {p.id} depends on non-indexed plug-in(s) {string.Join(",", unresolvedDeps)}"); } var resolvedDeps = deps.Where(d => d.resolved).Select(d => d.dep).ToList(); p.dependencies = resolvedDeps.AsReadOnly(); resolvedDeps.ForEach(d => d.dependants = d.dependants.Add(p)); } return(ImmutableArray.CreateRange(map.Values)); }
async Task <IReadOnlyList <IPluginInfo> > IPluginsManagerInternal.FetchAllPlugins(CancellationToken cancellation) { if (!pluginsIndexDownloader.IsDownloaderConfigured) { return(ImmutableArray.Create <IPluginInfo>()); } using (var resultStream = new MemoryStream()) { var result = await pluginsIndexDownloader.DownloadUpdate(pluginsIndex?.ETag, resultStream, cancellation); if (result.Status == AutoUpdate.DownloadUpdateResult.StatusCode.Failure) { this.tracer.Error("Failed to download plug-ins index: {0}", result.ErrorMessage); throw new Exception("Failed to fetch"); } else if (result.Status == AutoUpdate.DownloadUpdateResult.StatusCode.Success) { resultStream.Position = 0; pluginsIndex = pluginsIndexFactory.Create(resultStream, result.ETag); } return(MakePluginInfoList(pluginsIndex, pluginManifests, telemetry)); } }