public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, string outputPath, bool ignoreErrors, bool noLock, bool skipExisting, ILogger log) { var token = CancellationToken.None; ISleetFileSystemLock feedLock = null; var success = true; var perfTracker = source.LocalCache.PerfTracker; using (var timer = PerfEntryWrapper.CreateSummaryTimer("Total execution time: {0}", perfTracker)) { // Check if already initialized try { if (!noLock) { // Lock feedLock = await SourceUtility.VerifyInitAndLock(settings, source, "Download", log, token); // Validate source await UpgradeUtility.EnsureCompatibility(source, log, token); } success = await DownloadPackages(settings, source, outputPath, ignoreErrors, log, token); } finally { feedLock?.Dispose(); } } // Write out perf summary await perfTracker.LogSummary(log); return(success); }
public static async Task <bool> RunAsync( LocalSettings settings, ISleetFileSystem source, bool unsetAll, bool getAll, IEnumerable <string> getSettings, IEnumerable <string> unsetSettings, IEnumerable <string> setSettings, ILogger log, CancellationToken token) { log.LogMinimal($"Reading feed {source.BaseURI.AbsoluteUri}"); // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, "Feed settings", log, token)) { // Validate source await UpgradeUtility.EnsureCompatibility(source, log, token); var success = await ApplySettingsAsync(source, unsetAll, getAll, getSettings, unsetSettings, setSettings, log, token); log.LogMinimal($"Run 'recreate' to rebuild the feed with the new settings."); return(success); } }
/// <summary> /// Run prune /// 1. Lock the feed /// 2. Verify client compat /// 3. Prune packges /// 4. Commit /// </summary> public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, RetentionPruneCommandContext pruneContext, ILogger log) { var exitCode = true; log.LogMinimal($"Pruning packages in {source.BaseURI}"); var token = CancellationToken.None; // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, "Prune", log, token)) { // Validate source await UpgradeUtility.EnsureCompatibility(source, log, token); // Get sleet.settings.json var sourceSettings = await FeedSettingsUtility.GetSettingsOrDefault(source, log, token); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; exitCode = await PrunePackages(context, pruneContext); } return(exitCode); }
public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, List <string> inputs, bool force, bool skipExisting, ILogger log) { var token = CancellationToken.None; var now = DateTimeOffset.UtcNow; var success = false; var perfTracker = source.LocalCache.PerfTracker; await log.LogAsync(LogLevel.Minimal, $"Reading feed {source.BaseURI.AbsoluteUri}"); using (var timer = PerfEntryWrapper.CreateSummaryTimer("Total execution time: {0}", perfTracker)) { // Partition package inputs to avoid reading 100K nuspecs at the same time. var packagePaths = GetPackagePaths(inputs); var inputBatches = packagePaths.Partition(DefaultBatchSize); ISleetFileSystemLock feedLock = null; try { for (var i = 0; i < inputBatches.Count; i++) { var inputBatch = inputBatches[i]; if (inputBatches.Count > 1) { await log.LogAsync(LogLevel.Minimal, $"Pushing {inputBatch.Count} packages. Batch: {i+1} / {inputBatches.Count}"); } // Read packages before locking the feed the first time. var packages = new List <PackageInput>(await GetPackageInputs(inputBatch, now, perfTracker, log)); if (feedLock == null) { string lockMessage = null; if (packages.Count > 0) { lockMessage = $"Push of {packages[0].Identity.ToString()}"; } // Check if already initialized feedLock = await SourceUtility.VerifyInitAndLock(settings, source, lockMessage, log, token); // Validate source await SourceUtility.ValidateFeedForClient(source, log, token); } // Push success = await PushPackages(settings, source, packages, force, skipExisting, log, token); } } finally { // Unlock the feed feedLock?.Dispose(); } } // Write out perf summary await perfTracker.LogSummary(log); return(success); }
public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, ILogger log) { var token = CancellationToken.None; using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, log, token)) { return(await Destroy(settings, source, log, token)); } }
/// <summary> /// Lock the feed and delete all packages given. /// </summary> public static async Task <bool> DeletePackagesAsync(LocalSettings settings, ISleetFileSystem source, IEnumerable <PackageIdentity> packagesToDelete, string reason, bool force, ILogger log) { var success = true; var token = CancellationToken.None; log.LogMinimal($"Reading feed {source.BaseURI.AbsoluteUri}"); // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, "Delete", log, token)) { // Validate source await SourceUtility.ValidateFeedForClient(source, log, token); // Get sleet.settings.json var sourceSettings = await FeedSettingsUtility.GetSettingsOrDefault(source, log, token); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; var packageIndex = new PackageIndex(context); var existingPackageSets = await packageIndex.GetPackageSetsAsync(); var packages = new HashSet <PackageIdentity>(packagesToDelete); if (string.IsNullOrEmpty(reason)) { reason = string.Empty; } await RemovePackages(force, log, context, existingPackageSets, packages); // Save all log.LogMinimal($"Committing changes to {source.BaseURI.AbsoluteUri}"); success &= await source.Commit(log, token); } if (success) { log.LogMinimal($"Successfully deleted packages."); } else { log.LogError($"Failed to delete packages."); } return(success); }
public static async Task <int> RunCore(LocalSettings settings, ISleetFileSystem source, List <string> inputs, bool force, ILogger log) { var exitCode = 0; var token = CancellationToken.None; var now = DateTimeOffset.UtcNow; // Get packages var packages = GetPackageInputs(inputs, now, log); // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(source, log, token)) { // Validate source await UpgradeUtility.UpgradeIfNeeded(source, log, token); // Get sleet.settings.json var sourceSettings = new SourceSettings(); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; var packageIndex = new PackageIndex(context); foreach (var package in packages) { if (await packageIndex.Exists(package.Identity)) { if (force) { log.LogInformation($"Package already exists, removing {package.ToString()}"); await SleetUtility.RemovePackage(context, package.Identity); } else { throw new InvalidOperationException($"Package already exists: '{package.Identity}'."); } } log.LogInformation($"Adding {package.Identity.ToString()}"); await SleetUtility.AddPackage(context, package); } // Save all await source.Commit(log, token); } return(exitCode); }
public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, string outputPath, bool ignoreErrors, ILogger log) { var token = CancellationToken.None; // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, log, token)) { // Validate source await UpgradeUtility.EnsureFeedVersionMatchesTool(source, log, token); return(await DownloadPackages(settings, source, outputPath, ignoreErrors, log, token)); } }
public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, ILogger log) { var token = CancellationToken.None; log.LogMinimal($"Reading feed {source.BaseURI.AbsoluteUri}"); // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, log, token)) { // Validate source await SourceUtility.ValidateFeedForClient(source, log, token); return(await Validate(settings, source, log, token)); } }
public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, List <string> inputs, bool force, bool skipExisting, ILogger log) { var token = CancellationToken.None; await log.LogAsync(LogLevel.Minimal, $"Reading feed {source.BaseURI.AbsoluteUri}"); // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, log, token)) { // Validate source await SourceUtility.ValidateFeedForClient(source, log, token); return(await PushPackages(settings, source, inputs, force, skipExisting, log, token)); } }
public static JObject GetConfigFromEnv(Dictionary <string, string> mappings) { JObject json = null; var feedType = SourceUtility.GetFeedType(GetTokenValue(EnvVarFeedType, mappings, null)); if (feedType != FileSystemStorageType.Unspecified) { json = new JObject(); var sources = new JArray(); var source = new JObject(); sources.Add(source); json["sources"] = sources; var proxy = new JObject(); json["proxy"] = proxy; proxy["useDefaultCredentials"] = IsTrue(GetTokenValue($"{EnvVarPrefix}PROXY_USEDEFAULTCREDENTIALS", mappings, string.Empty)); json["username"] = GetTokenValue($"{EnvVarPrefix}USERNAME", mappings, string.Empty); json["useremail"] = GetTokenValue($"{EnvVarPrefix}USEREMAIL", mappings, string.Empty); // keep a default name to avoid confusion source["name"] = "envirnoment_feed"; // load all env vars with SLEET_FEED_ into the source config // prefer mappings over env vars var entries = GetSleetEnvVars(); if (mappings != null) { entries = entries.Concat(mappings); } foreach (var pair in entries) { if (pair.Key.StartsWith(EnvVarPrefix, StringComparison.OrdinalIgnoreCase)) { var innerKey = pair.Key.Substring(EnvVarPrefix.Length).ToLowerInvariant(); if (innerKey.Length > 0 && innerKey != "name") { source[innerKey] = ResolveTokens(pair.Value, mappings) ?? string.Empty; } } } } return(json); }
public static async Task <int> RunCore(LocalSettings settings, ISleetFileSystem source, ILogger log) { var exitCode = 0; log.LogMinimal($"Stats for {source.BaseURI}"); var token = CancellationToken.None; // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(source, log, token)) { // Validate source await UpgradeUtility.UpgradeIfNeeded(source, log, token); // Get sleet.settings.json var sourceSettings = new SourceSettings(); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; var catalog = new Catalog(context); var existingEntries = await catalog.GetExistingPackagesIndex(); var packages = existingEntries.Select(e => e.PackageIdentity).ToList(); var uniqueIds = packages.Select(e => e.Id).Distinct(StringComparer.OrdinalIgnoreCase); var catalogEntries = await catalog.GetIndexEntries(); log.LogMinimal($"Catalog entries: {catalogEntries.Count}"); log.LogMinimal($"Packages: {existingEntries.Count}"); log.LogMinimal($"Unique package ids: {uniqueIds.Count()}"); } return(exitCode); }
public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, ILogger log) { var exitCode = true; log.LogMinimal($"Stats for {source.BaseURI}"); var token = CancellationToken.None; // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, "Stats", log, token)) { // Validate source await UpgradeUtility.EnsureFeedVersionMatchesTool(source, log, token); // Get sleet.settings.json var sourceSettings = await FeedSettingsUtility.GetSettingsOrDefault(source, log, token); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; var packageIndex = new PackageIndex(context); var existingPackageSets = await packageIndex.GetPackageSetsAsync(); var uniqueIds = existingPackageSets.Packages.Index .Concat(existingPackageSets.Symbols.Index) .Select(e => e.Id).Distinct(StringComparer.OrdinalIgnoreCase); log.LogMinimal($"Packages: {existingPackageSets.Packages.Index.Count}"); log.LogMinimal($"Symbols Packages: {existingPackageSets.Symbols.Index.Count}"); log.LogMinimal($"Unique package ids: {uniqueIds.Count()}"); } return(exitCode); }
public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, List <string> inputs, bool force, bool skipExisting, ILogger log) { var token = CancellationToken.None; var now = DateTimeOffset.UtcNow; var packages = new List <PackageInput>(); await log.LogAsync(LogLevel.Minimal, $"Reading feed {source.BaseURI.AbsoluteUri}"); // Read packages before locking the feed. packages.AddRange(await GetPackageInputs(inputs, now, log)); // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, log, token)) { // Validate source await SourceUtility.ValidateFeedForClient(source, log, token); // Push return(await PushPackages(settings, source, packages, force, skipExisting, log, token)); } }
/// <summary> /// Enable/Disable retention and commit /// </summary> public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, int stableVersionMax, int prereleaseVersionMax, bool disableRetention, ILogger log) { var exitCode = false; log.LogMinimal($"Updating package retention settings in {source.BaseURI}"); var token = CancellationToken.None; // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, "Prune", log, token)) { // Validate source await UpgradeUtility.EnsureCompatibility(source, log, token); // Get sleet.settings.json var sourceSettings = await FeedSettingsUtility.GetSettingsOrDefault(source, log, token); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; if (disableRetention && stableVersionMax < 1 && prereleaseVersionMax < 1) { // Remove settings exitCode = await DisableRetention(context); } else if (stableVersionMax > 0 && prereleaseVersionMax > 0) { // Add max version settings exitCode = await UpdateRetentionSettings(context, stableVersionMax, prereleaseVersionMax); } } return(exitCode); }
public static async Task <bool> RunAsync( LocalSettings settings, ISleetFileSystem source, bool unsetAll, bool getAll, IEnumerable <string> getSettings, IEnumerable <string> unsetSettings, IEnumerable <string> setSettings, ILogger log, CancellationToken token) { log.LogMinimal($"Reading feed {source.BaseURI.AbsoluteUri}"); // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, "Feed settings", log, token)) { // Validate source await UpgradeUtility.EnsureCompatibility(source, log, token); // Get sleet.settings.json var sourceSettings = await FeedSettingsUtility.GetSettingsOrDefault(source, log, token); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; var success = await ApplySettingsAsync(context, unsetAll, getAll, getSettings, unsetSettings, setSettings); log.LogMinimal($"Run 'recreate' to rebuild the feed with the new settings."); return(success); } }
public static async Task <int> RunCore(LocalSettings settings, ISleetFileSystem source, string packageId, string version, string reason, bool force, ILogger log) { var exitCode = 0; var token = CancellationToken.None; var now = DateTimeOffset.UtcNow; // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(source, log, token)) { // Validate source await UpgradeUtility.UpgradeIfNeeded(source, log, token); // Get sleet.settings.json var sourceSettings = new SourceSettings(); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; var packageIndex = new PackageIndex(context); var packages = new List <PackageIdentity>(); if (!string.IsNullOrEmpty(version)) { // Delete a single version of the package var packageVersion = NuGetVersion.Parse(version); packages.Add(new PackageIdentity(packageId, packageVersion)); } else { // Delete all versions of the package packages.AddRange(await packageIndex.GetPackagesById(packageId)); } if (string.IsNullOrEmpty(reason)) { reason = string.Empty; } foreach (var package in packages) { if (!await packageIndex.Exists(package)) { log.LogInformation($"{package.ToString()} does not exist."); if (force) { // ignore failures continue; } else { throw new InvalidOperationException($"Package does not exists: {package.ToString()}"); } } log.LogInformation($"Removing {package.ToString()}"); await SleetUtility.RemovePackage(context, package); } // Save all await source.Commit(log, token); } return(exitCode); }
public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, string tmpPath, bool force, ILogger log) { var success = true; var cleanNupkgs = true; var token = CancellationToken.None; LocalCache localCache = null; // Use the tmp path if provided if (string.IsNullOrEmpty(tmpPath)) { localCache = new LocalCache(); } else { localCache = new LocalCache(tmpPath); } log.LogMinimal($"Reading feed {source.BaseURI.AbsoluteUri}"); using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, "Recreate", log, token)) { if (!force) { // Validate source await UpgradeUtility.EnsureCompatibility(source, log : log, token : token); } // Read settings and persist them in the new feed. var feedSettings = await FeedSettingsUtility.GetSettingsOrDefault(source, log, token); try { var downloadSuccess = await DownloadCommand.DownloadPackages(settings, source, localCache.Root.FullName, force, log, token); if (!force && !downloadSuccess) { log.LogError("Unable to recreate the feed due to errors download packages. Use --force to skip this check."); return(false); } var destroySuccess = await DestroyCommand.Destroy(settings, source, log, token); if (!force && !destroySuccess) { log.LogError("Unable to completely remove the old feed before recreating. Use --force to skip this check."); return(false); } var initSuccess = await InitCommand.InitAsync(settings, source, feedSettings, log, token); if (!initSuccess) { cleanNupkgs = false; log.LogError("Unable to initialize the new feed. The feed is currently broken and must be repaired manually."); success = false; return(false); } // Skip pushing for empty feeds if (Directory.GetFiles(localCache.Root.FullName, "*.*", SearchOption.AllDirectories).Length > 0) { var pushSuccess = await PushCommand.PushPackages(settings, source, new List <string>() { localCache.Root.FullName }, force : true, skipExisting : true, log : log, token : token); if (!pushSuccess) { cleanNupkgs = false; log.LogError("Unable to push packages to the new feed. Try pushing the nupkgs again manually."); success = false; return(false); } } var validateSuccess = await ValidateCommand.Validate(settings, source, log, token); if (!validateSuccess) { cleanNupkgs = false; log.LogError("Something went wrong when recreating the feed. Feed validation has failed."); success = false; return(false); } } finally { if (cleanNupkgs) { // Delete downloaded nupkgs log.LogInformation($"Removing local nupkgs from {localCache.Root.FullName}"); localCache.Dispose(); } else { var message = $"Encountered an error while recreating the feed. You may need to manually create the feed and push the nupkgs again. Nupkgs have been saved to: {localCache.Root.FullName}"; if (force) { log.LogWarning(message); } else { log.LogError(message); } } } log.LogMinimal("Feed recreation complete."); } return(success); }
public static async Task <bool> InitAsync(LocalSettings settings, ISleetFileSystem source, FeedSettings feedSettings, ILogger log, CancellationToken token) { SourceUtility.ValidateFileSystem(source); var exitCode = true; var noChanges = true; var now = DateTimeOffset.UtcNow; var context = new SleetContext() { LocalSettings = settings, Source = source, SourceSettings = feedSettings, Log = log, Token = token, OperationStart = now }; log.LogMinimal($"Initializing {source.BaseURI.AbsoluteUri}"); // Validate source var exists = await source.Validate(log, token); if (!exists) { return(false); } // Create service index.json noChanges &= !await CreateServiceIndexAsync(source, log, token, now); var serviceIndexFile = source.Get("index.json"); var serviceIndexJson = await serviceIndexFile.GetJson(log, token); var serviceIndexJsonBefore = serviceIndexJson.DeepClone(); serviceIndexJson["resources"] = new JArray(); // Create sleet.settings.json noChanges &= !await CreateSettingsAsync(source, feedSettings, log, token, now, serviceIndexJson); // Create catalog/index.json if (feedSettings.CatalogEnabled) { noChanges &= !await CreateCatalogAsync(source, log, token, now, serviceIndexJson); } // Create autocomplete noChanges &= !await CreateAutoCompleteAsync(source, log, token, now, serviceIndexJson); // Create search noChanges &= !await CreateSearchAsync(source, log, token, now, serviceIndexJson); // Create package index noChanges &= !await CreatePackageIndexAsync(context, serviceIndexJson); // Additional entries AddServiceIndexEntry(source.BaseURI, "registration/", "RegistrationsBaseUrl/3.4.0", "Package registrations used for search and packages.config.", serviceIndexJson); AddServiceIndexEntry(source.BaseURI, "", "ReportAbuseUriTemplate/3.0.0", "Report abuse template.", serviceIndexJson); AddServiceIndexEntry(source.BaseURI, "flatcontainer/", "PackageBaseAddress/3.0.0", "Packages used by project.json", serviceIndexJson); // Add symbols feed if enabled if (feedSettings.SymbolsEnabled) { await AddSymbolsFeedAsync(source, serviceIndexJson, context); } // Check if services changed noChanges &= serviceIndexJsonBefore.Equals(serviceIndexJson); if (noChanges) { throw new InvalidOperationException("Source is already initialized. No actions taken."); } // Write the service index out await serviceIndexFile.Write(serviceIndexJson, log, token); // Save all exitCode &= await source.Commit(log, token); if (exitCode) { log.LogMinimal($"Successfully initialized {source.BaseURI.AbsoluteUri}"); } else { log.LogError($"Failed to initialize {source.BaseURI.AbsoluteUri}"); } return(exitCode); }
public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, string packageId, string version, string reason, bool force, ILogger log) { var success = true; var token = CancellationToken.None; var now = DateTimeOffset.UtcNow; log.LogMinimal($"Reading feed {source.BaseURI.AbsoluteUri}"); // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(settings, source, log, token)) { // Validate source await SourceUtility.ValidateFeedForClient(source, log, token); // Get sleet.settings.json var sourceSettings = await FeedSettingsUtility.GetSettingsOrDefault(source, log, token); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; var packageIndex = new PackageIndex(context); var packages = new List <PackageIdentity>(); if (!string.IsNullOrEmpty(version)) { // Delete a single version of the package var packageVersion = NuGetVersion.Parse(version); packages.Add(new PackageIdentity(packageId, packageVersion)); } else { // Delete all versions of the package packages.AddRange(await packageIndex.GetPackagesByIdAsync(packageId)); } if (string.IsNullOrEmpty(reason)) { reason = string.Empty; } foreach (var package in packages) { var exists = await packageIndex.Exists(package); var symbolsExists = await packageIndex.SymbolsExists(package); if (!exists && !symbolsExists) { log.LogInformation($"{package.ToString()} does not exist."); if (force) { // ignore failures continue; } else { throw new InvalidOperationException($"Package does not exists: {package.ToString()}"); } } var message = $"Removing {package.ToString()}"; if (exists && symbolsExists) { message = $"Removing {package.ToString()} and symbols package for {package.ToString()}"; } else if (symbolsExists) { message = $"Removing symbols package {package.ToString()}"; } await log.LogAsync(LogLevel.Information, message); await SleetUtility.RemovePackage(context, package); } // Save all log.LogMinimal($"Committing changes to {source.BaseURI.AbsoluteUri}"); success &= await source.Commit(log, token); } if (success) { log.LogMinimal($"Successfully deleted packages."); } else { log.LogError($"Failed to delete packages."); } return(success); }
public static async Task <int> RunCore(LocalSettings settings, ISleetFileSystem source, ILogger log) { var exitCode = 0; var token = CancellationToken.None; // Check if already initialized using (var feedLock = await SourceUtility.VerifyInitAndLock(source, log, token)) { // Validate source await UpgradeUtility.UpgradeIfNeeded(source, log, token); // Get sleet.settings.json var sourceSettings = new SourceSettings(); // Settings context used for all operations var context = new SleetContext() { LocalSettings = settings, SourceSettings = sourceSettings, Log = log, Source = source, Token = token }; // Create all services var catalog = new Catalog(context); var registrations = new Registrations(context); var flatContainer = new FlatContainer(context); var search = new Search(context); var autoComplete = new AutoComplete(context); var packageIndex = new PackageIndex(context); var services = new List <ISleetService>(); services.Add(catalog); services.Add(registrations); services.Add(flatContainer); services.Add(search); // Verify against the package index var indexedPackages = await packageIndex.GetPackages(); var allIndexIds = indexedPackages.Select(e => e.Id).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); // Verify auto complete log.LogMinimal($"Validating {autoComplete.Name}"); var autoCompleteIds = await autoComplete.GetPackageIds(); var missingACIds = allIndexIds.Except(autoCompleteIds).ToList(); var extraACIds = autoCompleteIds.Except(allIndexIds).ToList(); if (missingACIds.Count() > 0 || extraACIds.Count() > 0) { log.LogError("Missing autocomplete packages: " + string.Join(", ", missingACIds)); log.LogError("Extra autocomplete packages: " + string.Join(", ", extraACIds)); exitCode = 1; } else { log.LogMinimal("Autocomplete packages valid"); } // Verify everything else foreach (var service in services) { log.LogMinimal($"Validating {service.Name}"); var allPackagesService = service as IPackagesLookup; var byIdService = service as IPackageIdLookup; var servicePackages = new HashSet <PackageIdentity>(); // Use get all if possible if (allPackagesService != null) { servicePackages.UnionWith(await allPackagesService.GetPackages()); } else if (byIdService != null) { foreach (var id in allIndexIds) { servicePackages.UnionWith(await byIdService.GetPackagesById(id)); } } else { log.LogError($"Unable to get packages for {service.Name}"); continue; } var diff = new PackageDiff(indexedPackages, servicePackages); if (diff.HasErrors) { log.LogError(diff.ToString()); exitCode = 1; } else { log.LogMinimal(diff.ToString()); log.LogMinimal($"{service.Name} packages valid"); } } if (exitCode != 0) { log.LogError($"Feed invalid!"); } else { log.LogMinimal($"Feed valid"); } } return(exitCode); }