예제 #1
0
        /// <summary>
        /// Enable package retention and update settings.
        /// </summary>
        public static async Task <bool> UpdateRetentionSettings(SleetContext context, int stableVersionMax, int prereleaseVersionMax)
        {
            var exitCode = true;
            var log      = context.Log;

            var feedSettings = context.SourceSettings;

            feedSettings.RetentionMaxStableVersions     = stableVersionMax;
            feedSettings.RetentionMaxPrereleaseVersions = prereleaseVersionMax;

            await FeedSettingsUtility.SaveSettings(context.Source, feedSettings, log, context.Token);

            // Commit changes to source
            exitCode = await context.Source.Commit(log, context.Token);

            if (exitCode)
            {
                await log.LogAsync(LogLevel.Minimal, $"Successfully updated package retention settings. Stable: {stableVersionMax} Prerelease: {prereleaseVersionMax}.");

                await log.LogAsync(LogLevel.Minimal, $"Run prune to apply the new settings and remove packages from the feed.");
            }
            else
            {
                await log.LogAsync(LogLevel.Error, "Failed to update package retention settings.");
            }

            return(exitCode);
        }
예제 #2
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);
        }
예제 #3
0
        /// <summary>
        /// Remove package retention settings.
        /// </summary>
        public static async Task <bool> DisableRetention(SleetContext context)
        {
            var exitCode = true;
            var log      = context.Log;

            var feedSettings = context.SourceSettings;

            feedSettings.RetentionMaxStableVersions     = null;
            feedSettings.RetentionMaxPrereleaseVersions = null;

            await FeedSettingsUtility.SaveSettings(context.Source, feedSettings, log, context.Token);

            // Commit changes to source
            exitCode = await context.Source.Commit(log, context.Token);

            if (exitCode)
            {
                await log.LogAsync(LogLevel.Minimal, "Package retention disabled.");
            }
            else
            {
                await log.LogAsync(LogLevel.Error, "Failed to disable retention settings.");
            }

            return(exitCode);
        }
예제 #4
0
        public static async Task <bool> RunAsync(LocalSettings settings, ISleetFileSystem source, bool enableCatalog, bool enableSymbols, ILogger log, CancellationToken token)
        {
            var feedSettings = await FeedSettingsUtility.GetSettingsOrDefault(source, log, token);

            feedSettings.CatalogEnabled = enableCatalog;
            feedSettings.SymbolsEnabled = enableSymbols;

            return(await InitAsync(settings, source, feedSettings, log, token));
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        private static async Task <bool> CreateSettingsAsync(ISleetFileSystem source, FeedSettings feedSettings, ILogger log, CancellationToken token, DateTimeOffset now, JObject serviceIndexJson)
        {
            AddServiceIndexEntry(source.BaseURI, "sleet.settings.json", "http://schema.emgarten.com/sleet#SettingsFile/1.0.0", "Sleet feed settings.", serviceIndexJson);

            // Create new file.
            var result = await CreateFromTemplateAsync(source, log, now, "Settings", "sleet.settings.json", token);

            // Write out the current settings.
            await FeedSettingsUtility.SaveSettings(source, feedSettings, log, token);

            return(result);
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        /// <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);
        }
예제 #10
0
        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);
            }
        }
예제 #11
0
        /// <summary>
        /// Validate packages. This does not lock or verify the version of the feed.
        /// </summary>
        public static async Task <bool> Validate(LocalSettings settings, ISleetFileSystem source, ILogger log, CancellationToken token)
        {
            var success = true;

            // 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
            };

            // Create all services
            var services = new List <ISleetService>();

            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);

            if (context.SourceSettings.CatalogEnabled)
            {
                // Add the catalog only if it is enabled
                var catalog = new Catalog(context);
                services.Add(catalog);
            }

            services.Add(registrations);
            services.Add(flatContainer);
            services.Add(search);

            if (context.SourceSettings.SymbolsEnabled)
            {
                var symbols = new Symbols(context);
                services.Add(symbols);
            }

            // Verify against the package index
            var indexedPackages = await packageIndex.GetPackagesAsync();

            var allIndexIds = indexedPackages.Select(e => e.Id).Distinct(StringComparer.OrdinalIgnoreCase).ToList();

            // Get symbols packages from index
            var indexedSymbolsPackages = await packageIndex.GetSymbolsPackagesAsync();

            var allIndexSymbolsIds = indexedSymbolsPackages.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));
                success = false;
            }
            else
            {
                log.LogMinimal("Autocomplete packages valid");
            }

            // Verify everything else
            foreach (var service in services)
            {
                log.LogMinimal($"Validating {service.Name}");

                var validatableService = service as IValidatableService;
                if (validatableService != null)
                {
                    // Run internal validations if the service supports it.
                    var messages = await validatableService.ValidateAsync();

                    success &= messages.All(e => e.Level != LogLevel.Error);

                    foreach (var message in messages)
                    {
                        await log.LogAsync(message);
                    }
                }
                else
                {
                    var allPackagesService = service as IPackagesLookup;
                    var byIdService        = service as IPackageIdLookup;

                    var allSymbolsPackagesService = service as ISymbolsPackagesLookup;
                    var symbolsByIdService        = service as ISymbolsPackageIdLookup;

                    var servicePackages        = new HashSet <PackageIdentity>();
                    var serviceSymbolsPackages = new HashSet <PackageIdentity>();

                    // Non-Symbols packages
                    if (allPackagesService != null)
                    {
                        // Use get all if possible
                        servicePackages.UnionWith(await allPackagesService.GetPackagesAsync());
                    }
                    else if (byIdService != null)
                    {
                        foreach (var id in allIndexIds)
                        {
                            servicePackages.UnionWith(await byIdService.GetPackagesByIdAsync(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());

                        success = false;
                    }
                    else
                    {
                        log.LogMinimal(diff.ToString());
                        log.LogMinimal($"{service.Name} packages valid");
                    }

                    // Symbols packages
                    if (allSymbolsPackagesService != null)
                    {
                        // Use get all if possible
                        serviceSymbolsPackages.UnionWith(await allSymbolsPackagesService.GetSymbolsPackagesAsync());
                    }
                    else if (symbolsByIdService != null)
                    {
                        foreach (var id in allIndexSymbolsIds)
                        {
                            serviceSymbolsPackages.UnionWith(await symbolsByIdService.GetSymbolsPackagesByIdAsync(id));
                        }
                    }
                    else
                    {
                        // Symbols are not supported by this service
                        continue;
                    }

                    var symbolsDiff = new PackageDiff(indexedSymbolsPackages, serviceSymbolsPackages);

                    if (symbolsDiff.HasErrors)
                    {
                        log.LogError(symbolsDiff.ToString());
                        success = false;
                    }
                    else
                    {
                        log.LogMinimal(symbolsDiff.ToString());
                        log.LogMinimal($"{service.Name} symbols packages valid");
                    }
                }
            }

            if (success)
            {
                log.LogMinimal($"Feed valid");
            }
            else
            {
                log.LogError($"Feed invalid!");
            }

            return(success);
        }
예제 #12
0
        /// <summary>
        /// Download packages. This method does not lock the feed or verify the client version.
        /// </summary>
        public static async Task <bool> DownloadPackages(LocalSettings settings, ISleetFileSystem source, string outputPath, bool ignoreErrors, bool skipExisting, ILogger log, CancellationToken token)
        {
            if (string.IsNullOrEmpty(outputPath))
            {
                throw new ArgumentException("Missing output path parameter!");
            }

            var success = true;

            // 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
            };

            log.LogMinimal($"Reading feed {source.BaseURI.AbsoluteUri}");

            // Find all packages
            var packageIndex  = new PackageIndex(context);
            var flatContainer = new FlatContainer(context);
            var symbols       = new Symbols(context);

            // Discover all packages
            var packages = new List <KeyValuePair <PackageIdentity, ISleetFile> >();

            packages.AddRange((await packageIndex.GetPackagesAsync()).Select(e =>
                                                                             new KeyValuePair <PackageIdentity, ISleetFile>(e, context.Source.Get(flatContainer.GetNupkgPath(e)))));
            packages.AddRange((await packageIndex.GetSymbolsPackagesAsync()).Select(e =>
                                                                                    new KeyValuePair <PackageIdentity, ISleetFile>(e, symbols.GetSymbolsNupkgFile(e))));

            log.LogMinimal($"Downloading nupkgs to {outputPath}");

            // Run downloads
            var tasks   = packages.Select(e => new Func <Task <bool> >(() => DownloadPackageAsync(outputPath, skipExisting, log, e, token)));
            var results = await TaskUtils.RunAsync(tasks, useTaskRun : true, token : CancellationToken.None);

            var downloadSuccess = results.All(e => e);

            success &= downloadSuccess;

            if (packages.Count < 1)
            {
                log.LogWarning("The feed does not contain any packages.");
            }

            if (downloadSuccess)
            {
                if (packages.Count > 0)
                {
                    log.LogMinimal("Successfully downloaded packages.");
                }
            }
            else
            {
                var message = $"Failed to download all packages!";

                if (ignoreErrors)
                {
                    log.LogWarning(message);
                }
                else
                {
                    log.LogError(message);
                }
            }

            return(success);
        }
예제 #13
0
파일: DeleteCommand.cs 프로젝트: gmfx/Sleet
        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);
        }
예제 #14
0
        /// <summary>
        /// Download packages. This method does not lock the feed or verify the client version.
        /// </summary>
        public static async Task <bool> DownloadPackages(LocalSettings settings, ISleetFileSystem source, string outputPath, bool ignoreErrors, ILogger log, CancellationToken token)
        {
            if (string.IsNullOrEmpty(outputPath))
            {
                throw new ArgumentException("Missing output path parameter!");
            }

            var success = true;

            // 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
            };

            log.LogMinimal($"Reading feed {source.BaseURI.AbsoluteUri}");

            // Find all packages
            var packageIndex  = new PackageIndex(context);
            var flatContainer = new FlatContainer(context);
            var symbols       = new Symbols(context);

            // Discover all packages
            var packages = new List <KeyValuePair <PackageIdentity, ISleetFile> >();

            packages.AddRange((await packageIndex.GetPackagesAsync()).Select(e =>
                                                                             new KeyValuePair <PackageIdentity, ISleetFile>(e, context.Source.Get(flatContainer.GetNupkgPath(e)))));
            packages.AddRange((await packageIndex.GetSymbolsPackagesAsync()).Select(e =>
                                                                                    new KeyValuePair <PackageIdentity, ISleetFile>(e, symbols.GetSymbolsNupkgFile(e))));

            var tasks           = new List <Task <bool> >(MaxThreads);
            var downloadSuccess = true;

            log.LogMinimal($"Downloading nupkgs to {outputPath}");

            foreach (var pair in packages)
            {
                if (tasks.Count >= MaxThreads)
                {
                    downloadSuccess &= await CompleteTask(tasks);
                }

                var package   = pair.Key;
                var nupkgFile = pair.Value;

                var fileName = UriUtility.GetFileName(nupkgFile.EntityUri);

                // id/id.version.nupkg or id/id.version.symbols.nupkg
                var outputNupkgPath = Path.Combine(outputPath,
                                                   package.Id.ToLowerInvariant(),
                                                   fileName.ToLowerInvariant());

                log.LogInformation($"Downloading {outputNupkgPath}");

                tasks.Add(nupkgFile.CopyTo(outputNupkgPath, overwrite: true, log: log, token: token));
            }

            while (tasks.Count > 0)
            {
                downloadSuccess &= await CompleteTask(tasks);
            }

            success &= downloadSuccess;

            if (packages.Count < 1)
            {
                log.LogWarning("The feed does not contain any packages.");
            }

            if (downloadSuccess)
            {
                if (packages.Count > 0)
                {
                    log.LogMinimal("Successfully downloaded packages.");
                }
            }
            else
            {
                var message = $"Failed to download all packages!";

                if (ignoreErrors)
                {
                    log.LogWarning(message);
                }
                else
                {
                    log.LogError(message);
                }
            }

            return(success);
        }
예제 #15
0
        public static async Task <bool> ApplySettingsAsync(
            ISleetFileSystem source,
            bool unsetAll,
            bool getAll,
            IEnumerable <string> getSettings,
            IEnumerable <string> unsetSettings,
            IEnumerable <string> setSettings,
            ILogger log,
            CancellationToken token)
        {
            var feedSettings     = FeedSettingsUtility.GetSettingsFileFromFeed(source);
            var feedSettingsJson = await feedSettings.GetJson(log, CancellationToken.None);

            var settings = FeedSettingsUtility.GetSettings(feedSettingsJson);

            var getKeys   = new SortedSet <string>(getSettings, StringComparer.OrdinalIgnoreCase);
            var setKeys   = new SortedSet <string>(setSettings, StringComparer.OrdinalIgnoreCase);
            var unsetKeys = new SortedSet <string>(unsetSettings, StringComparer.OrdinalIgnoreCase);

            if ((getKeys.Count + setKeys.Count + unsetKeys.Count) == 0 && !unsetAll && !getAll)
            {
                throw new ArgumentException("No arguments specified.");
            }

            if (getAll)
            {
                getKeys.UnionWith(settings.Keys);
            }

            if (unsetAll)
            {
                unsetKeys.UnionWith(settings.Keys);
            }

            if (getKeys.Count > 0 && (setKeys.Count + unsetKeys.Count) > 0)
            {
                throw new ArgumentException("Invalid combination of arguments. Get may not be combined with set or unset.");
            }

            // Get
            foreach (var key in getKeys)
            {
                if (!settings.TryGetValue(key, out var value))
                {
                    value = "not found!";
                }

                log.LogMinimal($"{key} : {value}");
            }

            // Unset
            foreach (var key in unsetKeys)
            {
                if (settings.ContainsKey(key))
                {
                    settings.Remove(key);
                }
            }

            // Set
            var setKeysSeen = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var input in setKeys)
            {
                var parts = input.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);

                if (parts.Length != 2 || string.IsNullOrEmpty(parts[0]?.Trim()) || string.IsNullOrEmpty(parts[1]?.Trim()))
                {
                    throw new ArgumentException("Value must be in the form {key}:{value}. Invalid: '" + input + "'");
                }

                var key   = parts[0].Trim().ToLowerInvariant();
                var value = parts[1].Trim();

                if (!setKeysSeen.Add(key))
                {
                    throw new ArgumentException($"Duplicate values for '{key}'. This value may only be set once.");
                }

                if (settings.ContainsKey(key))
                {
                    settings[key] = value;
                }
                else
                {
                    settings.Add(key, value);
                }
            }

            if (setKeys.Count > 0 || unsetKeys.Count > 0)
            {
                FeedSettingsUtility.Set(feedSettingsJson, settings);

                log.LogMinimal($"Updating settings");

                await feedSettings.Write(feedSettingsJson, log, token);

                // Save all
                log.LogMinimal($"Committing changes to {source.BaseURI.AbsoluteUri}");

                return(await source.Commit(log, token));
            }

            return(true);
        }
예제 #16
0
        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);
        }
예제 #17
0
        public static async Task <bool> PushPackages(LocalSettings settings, ISleetFileSystem source, List <string> inputs, bool force, bool skipExisting, ILogger log, CancellationToken token)
        {
            var exitCode = true;
            var now      = DateTimeOffset.UtcNow;
            var packages = new List <PackageInput>();

            try
            {
                // Get packages
                packages.AddRange(GetPackageInputs(inputs, now, log));

                // 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
                };

                // Fetch feed
                await SleetUtility.FetchFeed(context);

                await log.LogAsync(LogLevel.Information, "Reading existing package index");

                var packageIndex = new PackageIndex(context);

                foreach (var package in packages)
                {
                    await PushPackage(package, context, packageIndex, force, skipExisting, log);
                }

                // Save all
                await log.LogAsync(LogLevel.Minimal, $"Committing changes to {source.BaseURI.AbsoluteUri}");

                await source.Commit(log, token);
            }
            finally
            {
                // Close all zip readers
                foreach (var package in packages)
                {
                    package.Dispose();
                }
            }

            if (exitCode)
            {
                await log.LogAsync(LogLevel.Minimal, "Successfully pushed packages.");
            }
            else
            {
                await log.LogAsync(LogLevel.Error, "Failed to push packages.");
            }

            return(exitCode);
        }