/// <summary> /// Given a list of updates to export, it finds all updates bundled with updates to be exported and adds them /// to the list as well. This is done recursively, until all bundled updates have been included /// </summary> /// <param name="updatesToExport">The updates to export. Bundled updates are added to this list</param> /// <param name="source">The update metadata to export from.</param> public static void CompleteTheListOfExportUpdates(List <Update> updatesToExport, IMetadataSource source) { bool additionalUpdatesFound = false; do { var additionalUpdates = new List <Identity>(); foreach (var selectedUpdate in updatesToExport) { if (selectedUpdate.IsBundle) { foreach (var bundledUpdate in selectedUpdate.BundledUpdates) { if (!updatesToExport.Any(u => u.Identity.Equals(bundledUpdate))) { additionalUpdates.Add(bundledUpdate); } } } } foreach (var additionalUpdate in additionalUpdates) { // Bundled updates should appear in the list before the updates that bundle them updatesToExport.Insert(0, source.GetUpdate(additionalUpdate)); } additionalUpdatesFound = additionalUpdates.Count > 0; } while (additionalUpdatesFound); }
/// <summary> /// Instantiate the server and serve updates from the local repo /// </summary> /// <param name="metadataSource">The update metadata source to serve updates from</param> /// <param name="filter">The filter for which updates to serve.</param> /// <param name="serviceConfig">Service configuration.</param> public ServerSyncWebService(IMetadataSource metadataSource, MetadataFilter filter, ServerSyncConfigData serviceConfig) { MetadataSource = metadataSource; ServiceConfiguration = serviceConfig; UpdatesFilter = filter; Categories = metadataSource.GetCategories(); FilteredUpdates = metadataSource.GetUpdates(filter).ToDictionary(u => u.Identity); // If an update contains bundled updates, those bundled updates must also be made available to downstream servers var bundledUpdates = FilteredUpdates.Values.Where(u => u.IsBundle).SelectMany(u => u.BundledUpdates).Distinct().ToList(); foreach (var bundledUpdateId in bundledUpdates) { if (!FilteredUpdates.ContainsKey(bundledUpdateId)) { FilteredUpdates.Add(bundledUpdateId, metadataSource.GetUpdate(bundledUpdateId)); } } // Build the lookup tables by products and classifications ProductsIndex = new Dictionary <Guid, List <Update> >(); ClassificationsIndex = new Dictionary <Guid, List <Update> >(); foreach (var update in FilteredUpdates.Values) { if (update.HasProduct) { foreach (var productId in update.ProductIds) { if (!ProductsIndex.ContainsKey(productId)) { ProductsIndex[productId] = new List <Update>(); } ProductsIndex[productId].Add(update); } } if (update.HasClassification) { foreach (var classificationId in update.ClassificationIds) { if (!ClassificationsIndex.ContainsKey(classificationId)) { ClassificationsIndex[classificationId] = new List <Update>(); } ClassificationsIndex[classificationId].Add(update); } } } }
static void PrintBundleChainRecursive(IMetadataSource source, Update update, int recursionIndex) { const int indentSize = 4; if (update.IsBundled) { foreach (var parentBundleID in update.BundleParent) { Console.CursorLeft = indentSize * recursionIndex + indentSize; Console.WriteLine("Bundled in : {0}", parentBundleID); Console.CursorLeft = indentSize * recursionIndex + indentSize; Console.WriteLine(" : {0}", source.GetUpdateTitle(parentBundleID)); PrintBundleChainRecursive(source, source.GetUpdate(parentBundleID), recursionIndex + 1); } } }