/// <summary> /// Prune feed packages without committing /// </summary> public static async Task <HashSet <PackageIdentity> > PrunePackagesNoCommit(SleetContext context, RetentionPruneCommandContext pruneContext) { var packageIndex = new PackageIndex(context); var existingPackageSets = await packageIndex.GetPackageSetsAsync(); var allPackages = await RetentionUtility.ResolvePackageSets(existingPackageSets); var stableMax = pruneContext.StableVersionMax == null ? context.SourceSettings.RetentionMaxStableVersions : pruneContext.StableVersionMax; var prerelMax = pruneContext.PrereleaseVersionMax == null ? context.SourceSettings.RetentionMaxPrereleaseVersions : pruneContext.PrereleaseVersionMax; if (stableMax == null || stableMax < 1) { throw new ArgumentException("Package retention must specify a maximum number of stable versions that is > 0"); } if (prerelMax == null || prerelMax < 1) { throw new ArgumentException("Package retention must specify a maximum number of prerelease versions that is > 0"); } if (pruneContext.PackageIds?.Count > 0) { allPackages.RemoveWhere(e => !pruneContext.PackageIds.Contains(e.Id)); } var toPrune = RetentionUtility.GetPackagesToPrune(allPackages, pruneContext.PinnedPackages, (int)stableMax, (int)prerelMax); await RemovePackages(context, existingPackageSets, toPrune, pruneContext.DryRun, context.Log); return(toPrune); }
/// <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); }
/// <summary> /// Push packages to a feed. /// This assumes the feed is already locked. /// </summary> public static async Task <bool> PushPackages(LocalSettings settings, ISleetFileSystem source, List <PackageInput> packages, bool force, bool skipExisting, ILogger log, CancellationToken token) { var exitCode = true; var now = DateTimeOffset.UtcNow; // Verify no duplicate packages CheckForDuplicates(packages); // Get sleet.settings.json await log.LogAsync(LogLevel.Minimal, "Reading feed"); 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, PerfTracker = source.LocalCache.PerfTracker }; await log.LogAsync(LogLevel.Verbose, "Reading existing package index"); // Push var packageIndex = new PackageIndex(context); var existingPackageSets = await packageIndex.GetPackageSetsAsync(); await PushPackages(packages, context, existingPackageSets, force, skipExisting, log); // Prune packages await PrunePackages(packages, context); // Save all await log.LogAsync(LogLevel.Minimal, $"Committing changes to {source.BaseURI.AbsoluteUri}"); await source.Commit(log, token); if (exitCode) { await log.LogAsync(LogLevel.Minimal, "Successfully pushed packages."); } else { await log.LogAsync(LogLevel.Error, "Failed to push packages."); } 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); }
private static async Task PushPackages(List<PackageInput> packageInputs, SleetContext context, PackageIndex packageIndex, bool force, bool skipExisting, ILogger log) { var toAdd = new List<PackageInput>(); var toRemove = new List<PackageInput>(); var existingPackageSets = await packageIndex.GetPackageSetsAsync(); foreach (var package in packageInputs) { var packageString = $"{package.Identity.Id} {package.Identity.Version.ToFullString()}"; if (package.IsSymbolsPackage) { packageString += " Symbols"; if (!context.SourceSettings.SymbolsEnabled) { await log.LogAsync(LogLevel.Warning, $"Skipping {packageString}, to push symbols packages enable the symbols server on this feed."); // Skip this package continue; } } var exists = false; if (package.IsSymbolsPackage) { exists = existingPackageSets.Symbols.Exists(package.Identity); } else { exists = existingPackageSets.Packages.Exists(package.Identity); } if (exists) { if (skipExisting) { await log.LogAsync(LogLevel.Minimal, $"Skip exisiting package: {packageString}"); continue; } else if (force) { toRemove.Add(package); await log.LogAsync(LogLevel.Information, $"Replace existing package: {packageString}"); } else { throw new InvalidOperationException($"Package already exists: {packageString}."); } } else { await log.LogAsync(LogLevel.Minimal, $"Add new package: {packageString}"); } // Add to list of packages to push toAdd.Add(package); } await log.LogAsync(LogLevel.Minimal, $"Processing feed changes"); // Add/Remove packages var changeContext = SleetOperations.Create(existingPackageSets, toAdd, toRemove); await SleetUtility.ApplyPackageChangesAsync(context, changeContext); }
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 existingPackageSets = await packageIndex.GetPackageSetsAsync(); var packages = new HashSet <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.UnionWith(await existingPackageSets.Packages.GetPackagesByIdAsync(packageId)); packages.UnionWith(await existingPackageSets.Symbols.GetPackagesByIdAsync(packageId)); } if (string.IsNullOrEmpty(reason)) { reason = string.Empty; } var toRemove = new HashSet <PackageIdentity>(); var toRemoveSymbols = new HashSet <PackageIdentity>(); foreach (var package in packages) { var exists = existingPackageSets.Packages.Exists(package); var symbolsExists = existingPackageSets.Symbols.Exists(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()}"); } } if (exists) { toRemove.Add(package); } if (symbolsExists) { toRemoveSymbols.Add(package); } 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); } // Update feed await log.LogAsync(LogLevel.Information, "Removing packages from feed locally"); // Add/Remove packages var changeContext = SleetOperations.CreateDelete(existingPackageSets, toRemove, toRemoveSymbols); await SleetUtility.ApplyPackageChangesAsync(context, changeContext); // 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); }
private static Task <PackageSets> GetPackageSets(SleetContext context) { var index = new PackageIndex(context); return(index.GetPackageSetsAsync()); }