private static void Run(CommandLineApplication cmd, ILogger log) { cmd.Description = "Prune feed packages."; var optionConfigFile = cmd.Option(Constants.ConfigOption, Constants.ConfigDesc, CommandOptionType.SingleValue); var sourceName = cmd.Option(Constants.SourceOption, Constants.SourceDesc, CommandOptionType.SingleValue); var verbose = cmd.Option(Constants.VerboseOption, Constants.VerboseDesc, CommandOptionType.NoValue); cmd.HelpOption(Constants.HelpOption); var stableVersions = cmd.Option("--stable", "Number of stable versions per package id. If not specified the feed settings will be used.", CommandOptionType.SingleValue); var prereleaseVersions = cmd.Option("--prerelease", "Number of prerelease versions per package id. If not specified the feed settings will be used.", CommandOptionType.SingleValue); var releaseLabelsValue = cmd.Option("--release-labels", "Group prerelease packages by the first X release labels. Each group will be pruned to the prerelease max if applied. (optional)", CommandOptionType.SingleValue); var packageIds = cmd.Option("--package", "Prune only the given package ids", CommandOptionType.MultipleValue); var dryRun = cmd.Option("--dry-run", "Print out all versions that would be deleted without actually removing them.", CommandOptionType.NoValue); var propertyOptions = cmd.Option(Constants.PropertyOption, Constants.PropertyDescription, CommandOptionType.MultipleValue); var required = new List <CommandOption>(); cmd.OnExecute(async() => { // Validate parameters CmdUtils.VerifyRequiredOptions(required.ToArray()); // Init logger Util.SetVerbosity(log, verbose.HasValue()); // Create a temporary folder for caching files during the operation. using (var cache = new LocalCache()) { // Load settings and file system. var settings = LocalSettings.Load(optionConfigFile.Value(), SettingsUtility.GetPropertyMappings(propertyOptions.Values)); var fileSystem = await Util.CreateFileSystemOrThrow(settings, sourceName.Value(), cache); var success = false; var pruneContext = new RetentionPruneCommandContext() { DryRun = dryRun.HasValue(), StableVersionMax = stableVersions.HasValue() ? (int?)int.Parse(stableVersions.Value()) : null, PrereleaseVersionMax = prereleaseVersions.HasValue() ? (int?)int.Parse(prereleaseVersions.Value()) : null, GroupByFirstPrereleaseLabelCount = releaseLabelsValue.HasValue() ? (int?)int.Parse(releaseLabelsValue.Value()) : null, }; if (packageIds.HasValue()) { pruneContext.PackageIds.UnionWith(packageIds.Values); } success = await RetentionPruneCommand.RunAsync(settings, fileSystem, pruneContext, log); return(success ? 0 : 1); } }); }
private static async Task PrunePackages(List <PackageInput> packages, SleetContext context) { // Run only if the package retention settings are present for the feed if (context.SourceSettings.RetentionMaxStableVersions > 0 && context.SourceSettings.RetentionMaxPrereleaseVersions > 0) { // Prune if prune is enabled for the feed var pruneContext = new RetentionPruneCommandContext(); // Do not prune packages that were just pushed pruneContext.PinnedPackages.UnionWith(packages.Select(e => e.Identity)); // Only prune package ids that were pushed pruneContext.PackageIds.UnionWith(packages.Select(e => e.Identity.Id)); // Run prune against the local files await RetentionPruneCommand.PrunePackagesNoCommit(context, pruneContext); } }
/// <summary> /// Prune feed packages and commit to source /// </summary> public static async Task <bool> PrunePackages(SleetContext context, RetentionPruneCommandContext pruneContext) { var exitCode = true; var log = context.Log; // Find packages to prune and remove them locally await PrunePackagesNoCommit(context, pruneContext); // Commit changes to source exitCode = await context.Source.Commit(log, context.Token); if (exitCode) { await log.LogAsync(LogLevel.Minimal, "Successfully pruned packages."); } else { await log.LogAsync(LogLevel.Error, "Failed to prune packages."); } return(exitCode); }
/// <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> /// 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); }