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);
                }
            });
        }
Beispiel #2
0
 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);
     }
 }
Beispiel #3
0
        /// <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);
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        /// <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);
        }