Ejemplo n.º 1
0
        async Task <IEnumerable <IPackageSearchMetadata> > GetPackagesWithUpdatesAsync(string searchText, SearchFilter searchFilter, CancellationToken cancellationToken)
        {
            if (_context != null)
            {
                _installedPackages = await _context.GetInstalledPackagesAsync();

                _context = null;
            }

            var packages = _installedPackages
                           .GetEarliest()
                           .Where(p => p.Id.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1)
                           .OrderBy(p => p.Id);

            var latestItems = await TaskCombinators.ThrottledAsync(
                packages,
                (p, t) => _metadataProvider.GetLatestPackageMetadataAsync(p, searchFilter.IncludePrerelease, t),
                cancellationToken);

            var packagesWithUpdates = packages
                                      .Join(latestItems.Where(i => i != null),
                                            p => p.Id,
                                            m => m.Identity.Id,
                                            (p, m) => new { cv = p.Version, m = m },
                                            StringComparer.OrdinalIgnoreCase)
                                      .Where(j => VersionComparer.VersionRelease.Compare(j.cv, j.m.Identity.Version) < 0)
                                      .Select(j => j.m);

            return(packagesWithUpdates);
        }
Ejemplo n.º 2
0
        // For unit testing purposes
        internal static async ValueTask <PackageItemLoader> CreateAsync(
            IServiceBroker serviceBroker,
            PackageLoadContext context,
            IReadOnlyCollection <PackageSourceContextInfo> packageSources,
            ContractItemFilter itemFilter,
            IReconnectingNuGetSearchService searchService,
            INuGetPackageFileService packageFileService,
            string searchText      = null,
            bool includePrerelease = true,
            bool useRecommender    = false)
        {
            var itemLoader = new PackageItemLoader(
                serviceBroker,
                searchService,
                context,
                packageSources,
                itemFilter,
                searchText,
                includePrerelease,
                useRecommender);

            await itemLoader.InitializeAsync(packageFileService);

            return(itemLoader);
        }
Ejemplo n.º 3
0
        private void RefreshAvailableUpdatesCount()
        {
            NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async() =>
            {
                await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                _topPanel._labelUpgradeAvailable.Count = 0;
                var loadContext = new PackageLoadContext(ActiveSources, Model.IsSolution, Model.Context);
                var packageFeed = await CreatePackageFeedAsync(loadContext, ItemFilter.UpdatesAvailable, _uiLogger);
                var loader      = new PackageItemLoader(
                    loadContext, packageFeed, includePrerelease: IncludePrerelease);

                // cancel previous refresh update count task, if any
                // and start a new one.
                var refreshCts = new CancellationTokenSource();
                Interlocked.Exchange(ref _refreshCts, refreshCts)?.Cancel();

                Model.CachedUpdates = new PackageSearchMetadataCache
                {
                    Packages          = await loader.GetAllPackagesAsync(refreshCts.Token),
                    IncludePrerelease = IncludePrerelease
                };

                _topPanel._labelUpgradeAvailable.Count = Model.CachedUpdates.Packages.Count;
            });
        }
        /// <summary>
        /// This method is called from several event handlers. So, consolidating the use of JTF.Run in this method
        /// </summary>
        private void SearchPackagesAndRefreshUpdateCount(string searchText, bool useCache)
        {
            NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async() =>
            {
                await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                var loadContext = new PackageLoadContext(ActiveSources, Model.IsSolution, Model.Context);

                if (useCache)
                {
                    loadContext.CachedPackages = Model.CachedUpdates;
                }
                ;

                var packageFeed = await CreatePackageFeedAsync(loadContext, _topPanel.Filter, _uiLogger);

                var loader = new PackageItemLoader(
                    loadContext, packageFeed, searchText, IncludePrerelease);
                var loadingMessage = string.IsNullOrWhiteSpace(searchText)
                    ? Resx.Resources.Text_Loading
                    : string.Format(CultureInfo.CurrentCulture, Resx.Resources.Text_Searching, searchText);

                // Set a new cancellation token source which will be used to cancel this task in case
                // new loading task starts or manager ui is closed while loading packages.
                _loadCts = new CancellationTokenSource();

                // start SearchAsync task for initial loading of packages
                var searchResultTask = loader.SearchAsync(continuationToken: null, cancellationToken: _loadCts.Token);

                // this will wait for searchResultTask to complete instead of creating a new task
                _packageList.LoadItems(loader, loadingMessage, _uiLogger, searchResultTask, _loadCts.Token);

                // We only refresh update count, when we don't use cache so check it it's false
                if (!useCache)
                {
                    // clear existing caches
                    Model.CachedUpdates = null;

                    if (_topPanel.Filter.Equals(ItemFilter.UpdatesAvailable))
                    {
                        // it means selected tab is update itself, so just wait for searchAsyncTask to complete
                        // without making another call to loader to get all packages.
                        _topPanel._labelUpgradeAvailable.Count = 0;

                        var searchResult    = await searchResultTask;
                        Model.CachedUpdates = new PackageSearchMetadataCache
                        {
                            Packages          = searchResult.Items,
                            IncludePrerelease = IncludePrerelease
                        };

                        _topPanel._labelUpgradeAvailable.Count = Model.CachedUpdates.Packages.Count;
                    }
                    else
                    {
                        RefreshAvailableUpdatesCount();
                    }
                }
            });
        }
Ejemplo n.º 5
0
        /// <summary>
        /// This method is called from several event handlers. So, consolidating the use of JTF.Run in this method
        /// </summary>
        private void SearchPackageInActivePackageSource(string searchText, bool useCache)
        {
            NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async() =>
            {
                await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                var loadContext = new PackageLoadContext(ActiveSources, Model.IsSolution, Model.Context);

                if (useCache)
                {
                    loadContext.CachedPackages = Model.CachedUpdates;
                }
                ;

                var packageFeed = await CreatePackageFeedAsync(loadContext, _topPanel.Filter, _uiLogger);

                var loader = new PackageItemLoader(
                    loadContext, packageFeed, searchText, IncludePrerelease);
                var loadingMessage = string.IsNullOrWhiteSpace(searchText)
                    ? Resx.Resources.Text_Loading
                    : string.Format(CultureInfo.CurrentCulture, Resx.Resources.Text_Searching, searchText);

                _packageList.LoadItems(loader, loadingMessage, _uiLogger);
            });
        }
Ejemplo n.º 6
0
 public ConsolidatePackageFeed(
     PackageLoadContext context,
     IPackageMetadataProvider metadataProvider,
     Common.ILogger logger)
     : this(new PackageIdentity[0], metadataProvider, logger)
 {
     _context = context;
 }
Ejemplo n.º 7
0
 public InstalledPackageFeed(
     PackageLoadContext context,
     IPackageMetadataProvider metadataProvider,
     Common.ILogger logger)
     : this(new PackageIdentity[0], metadataProvider, logger)
 {
     this._context = context;
 }
Ejemplo n.º 8
0
 public UpdatePackageFeed(
     PackageLoadContext context,
     IPackageMetadataProvider metadataProvider,
     PackageSearchMetadataCache cachedUpdates,
     Common.ILogger logger)
     : this(new PackageIdentity[0], metadataProvider, cachedUpdates, logger)
 {
     _context = context;
 }
Ejemplo n.º 9
0
        private static IPackageMetadataProvider CreatePackageMetadataProvider(PackageLoadContext context)
        {
            var logger = new VisualStudioActivityLogger();

            return(new MultiSourcePackageMetadataProvider(
                       context.SourceRepositories,
                       context.PackageManager?.PackagesFolderSourceRepository,
                       context.PackageManager?.GlobalPackageFolderRepositories,
                       logger));
        }
Ejemplo n.º 10
0
        private void RefreshConsolidatablePackagesCount()
        {
            NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async() =>
            {
                await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
                _topPanel._labelConsolidate.Count = 0;
                var loadContext = new PackageLoadContext(ActiveSources, Model.IsSolution, Model.Context);
                var packageFeed = await CreatePackageFeedAsync(loadContext, ItemFilter.Consolidate, _uiLogger);
                var loader      = new PackageItemLoader(
                    loadContext, packageFeed, includePrerelease: IncludePrerelease);

                _topPanel._labelConsolidate.Count = await loader.GetTotalCountAsync(100, CancellationToken.None);
            });
        }
        private static async Task <IPackageFeed> CreatePackageFeedAsync(PackageLoadContext context, ItemFilter filter, INuGetUILogger uiLogger)
        {
            // Go off the UI thread to perform non-UI operations
            await TaskScheduler.Default;

            var logger = new VisualStudioActivityLogger();

            if (filter == ItemFilter.All)
            {
                return(new MultiSourcePackageFeed(context.SourceRepositories, uiLogger));
            }

            var metadataProvider  = CreatePackageMetadataProvider(context);
            var installedPackages = await context.GetInstalledPackagesAsync();

            if (filter == ItemFilter.Installed)
            {
                return(new InstalledPackageFeed(installedPackages, metadataProvider, logger));
            }

            if (filter == ItemFilter.Consolidate)
            {
                return(new ConsolidatePackageFeed(installedPackages, metadataProvider, logger));
            }

            // Search all / updates available cannot work without a source repo
            if (context.SourceRepositories == null)
            {
                return(null);
            }

            if (filter == ItemFilter.UpdatesAvailable)
            {
                return(new UpdatePackageFeed(
                           installedPackages,
                           metadataProvider,
                           context.Projects,
                           context.CachedPackages,
                           logger));
            }

            throw new InvalidOperationException("Unsupported feed type");
        }
Ejemplo n.º 12
0
        private PackageItemLoader(
            IServiceBroker serviceBroker,
            PackageLoadContext context,
            IReadOnlyCollection <PackageSourceContextInfo> packageSources,
            ContractItemFilter itemFilter,
            string searchText,
            bool includePrerelease,
            bool useRecommender)
        {
            Assumes.NotNull(serviceBroker);
            Assumes.NotNull(context);
            Assumes.NotNullOrEmpty(packageSources);

            _serviceBroker     = serviceBroker;
            _context           = context;
            _searchText        = searchText ?? string.Empty;
            _includePrerelease = includePrerelease;
            _packageSources    = packageSources;
            _itemFilter        = itemFilter;
            _useRecommender    = useRecommender;
        }
Ejemplo n.º 13
0
        public PackageItemLoader(
            PackageLoadContext context,
            IPackageFeed packageFeed,
            string searchText      = null,
            bool includePrerelease = true)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            _context = context;

            if (packageFeed == null)
            {
                throw new ArgumentNullException(nameof(packageFeed));
            }
            _packageFeed = packageFeed;

            _searchText        = searchText ?? string.Empty;
            _includePrerelease = includePrerelease;
        }
Ejemplo n.º 14
0
        private void RefreshAvailableUpdatesCount()
        {
            NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async() =>
            {
                await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                _topPanel._labelUpgradeAvailable.Count = 0;
                var loadContext = new PackageLoadContext(ActiveSources, Model.IsSolution, Model.Context);
                var packageFeed = await CreatePackageFeedAsync(loadContext, ItemFilter.UpdatesAvailable, _uiLogger);
                var loader      = new PackageItemLoader(
                    loadContext, packageFeed, includePrerelease: IncludePrerelease);

                Model.CachedUpdates = new PackageSearchMetadataCache
                {
                    Packages          = await loader.GetAllPackagesAsync(CancellationToken.None),
                    IncludePrerelease = IncludePrerelease
                };

                _topPanel._labelUpgradeAvailable.Count = Model.CachedUpdates.Packages.Count;
            });
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Updates the detail pane based on the selected package
        /// </summary>
        private async Task UpdateDetailPaneAsync()
        {
            var selectedPackage = _packageList.SelectedItem;

            if (selectedPackage == null)
            {
                _packageDetail.Visibility  = Visibility.Hidden;
                _packageDetail.DataContext = null;
            }
            else
            {
                _packageDetail.Visibility  = Visibility.Visible;
                _packageDetail.DataContext = _detailModel;

                await _detailModel.SetCurrentPackage(selectedPackage, _topPanel.Filter, () => _packageList.SelectedItem);

                _packageDetail.ScrollToHome();

                var context          = new PackageLoadContext(ActiveSources, Model.IsSolution, Model.Context);
                var metadataProvider = CreatePackageMetadataProvider(context);
                await _detailModel.LoadPackageMetadaAsync(metadataProvider, CancellationToken.None);
            }
        }
Ejemplo n.º 16
0
        private async Task PerformActionImplAsync(
            IServiceBroker serviceBroker,
            INuGetProjectManagerService projectManagerService,
            INuGetUI uiService,
            ResolveActionsAsync resolveActionsAsync,
            NuGetOperationType operationType,
            UserAction userAction,
            CancellationToken cancellationToken)
        {
            var status       = NuGetOperationStatus.Succeeded;
            var startTime    = DateTimeOffset.Now;
            var packageCount = 0;

            var continueAfterPreview = true;
            var acceptedLicense      = true;

            List <string> removedPackages  = null;
            var           existingPackages = new HashSet <Tuple <string, string> >();
            List <Tuple <string, string> > addedPackages      = null;
            List <Tuple <string, string> > updatedPackagesOld = null;
            List <Tuple <string, string> > updatedPackagesNew = null;

            // Enable granular level telemetry events for nuget ui operation
            uiService.ProjectContext.OperationId = Guid.NewGuid();

            Stopwatch packageEnumerationTime = new Stopwatch();

            packageEnumerationTime.Start();
            try
            {
                // collect the install state of the existing packages
                foreach (IProjectContextInfo project in uiService.Projects)
                {
                    IEnumerable <IPackageReferenceContextInfo> installedPackages = await project.GetInstalledPackagesAsync(
                        uiService.UIContext.ServiceBroker,
                        cancellationToken);

                    foreach (IPackageReferenceContextInfo package in installedPackages)
                    {
                        Tuple <string, string> packageInfo = new Tuple <string, string>(
                            package.Identity.Id,
                            (package.Identity.Version == null ? "" : package.Identity.Version.ToNormalizedString()));

                        if (!existingPackages.Contains(packageInfo))
                        {
                            existingPackages.Add(packageInfo);
                        }
                    }
                }
            }
            catch (Exception)
            {
                // don't teardown the process if we have a telemetry failure
            }
            packageEnumerationTime.Stop();

            await _lockService.ExecuteNuGetOperationAsync(async() =>
            {
                try
                {
                    uiService.BeginOperation();

                    using (INuGetProjectUpgraderService projectUpgrader = await serviceBroker.GetProxyAsync <INuGetProjectUpgraderService>(
                               NuGetServices.ProjectUpgraderService,
                               cancellationToken))
                    {
                        bool isAcceptedFormat = await CheckPackageManagementFormatAsync(projectUpgrader, uiService, cancellationToken);
                        if (!isAcceptedFormat)
                        {
                            return;
                        }
                    }

                    TelemetryServiceUtility.StartOrResumeTimer();

                    IReadOnlyList <ProjectAction> actions = await resolveActionsAsync(projectManagerService);
                    IReadOnlyList <PreviewResult> results = await GetPreviewResultsAsync(projectManagerService, actions, cancellationToken);

                    if (operationType == NuGetOperationType.Uninstall)
                    {
                        // removed packages don't have version info
                        removedPackages = results.SelectMany(result => result.Deleted)
                                          .Select(package => package.Id)
                                          .Distinct()
                                          .ToList();
                        packageCount = removedPackages.Count;
                    }
                    else
                    {
                        // log rich info about added packages
                        addedPackages = results.SelectMany(result => result.Added)
                                        .Select(package => new Tuple <string, string>(package.Id, (package.Version == null ? "" : package.Version.ToNormalizedString())))
                                        .Distinct()
                                        .ToList();
                        var addCount = addedPackages.Count;

                        //updated packages can have an old and a new id.
                        updatedPackagesOld = results.SelectMany(result => result.Updated)
                                             .Select(package => new Tuple <string, string>(package.Old.Id, (package.Old.Version == null ? "" : package.Old.Version.ToNormalizedString())))
                                             .Distinct()
                                             .ToList();
                        updatedPackagesNew = results.SelectMany(result => result.Updated)
                                             .Select(package => new Tuple <string, string>(package.New.Id, (package.New.Version == null ? "" : package.New.Version.ToNormalizedString())))
                                             .Distinct()
                                             .ToList();
                        var updateCount = updatedPackagesNew.Count;

                        // update packages count
                        packageCount = addCount + updateCount;

                        if (updateCount > 0)
                        {
                            // set operation type to update when there are packages being updated
                            operationType = NuGetOperationType.Update;
                        }
                    }

                    TelemetryServiceUtility.StopTimer();

                    // Show the preview window.
                    if (uiService.DisplayPreviewWindow)
                    {
                        bool shouldContinue = uiService.PromptForPreviewAcceptance(results);
                        if (!shouldContinue)
                        {
                            continueAfterPreview = false;
                            return;
                        }
                    }

                    TelemetryServiceUtility.StartOrResumeTimer();

                    // Show the license acceptance window.
                    bool accepted = await CheckLicenseAcceptanceAsync(uiService, results, cancellationToken);

                    TelemetryServiceUtility.StartOrResumeTimer();

                    if (!accepted)
                    {
                        acceptedLicense = false;
                        return;
                    }

                    // Warn about the fact that the "dotnet" TFM is deprecated.
                    if (uiService.DisplayDeprecatedFrameworkWindow)
                    {
                        bool shouldContinue = await ShouldContinueDueToDotnetDeprecationAsync(projectManagerService, uiService, cancellationToken);

                        TelemetryServiceUtility.StartOrResumeTimer();

                        if (!shouldContinue)
                        {
                            return;
                        }
                    }

                    if (!cancellationToken.IsCancellationRequested)
                    {
                        await projectManagerService.ExecuteActionsAsync(
                            actions,
                            cancellationToken);

                        string[] projectIds = actions
                                              .Select(action => action.ProjectId)
                                              .Distinct()
                                              .ToArray();

                        uiService.UIContext.RaiseProjectActionsExecuted(projectIds);
                    }
                    else
                    {
                        status = NuGetOperationStatus.Cancelled;
                    }
                }
                catch (System.Net.Http.HttpRequestException ex)
                {
                    status = NuGetOperationStatus.Failed;
                    if (ex.InnerException != null)
                    {
                        uiService.ShowError(ex.InnerException);
                    }
                    else
                    {
                        uiService.ShowError(ex);
                    }
                }
                catch (Exception ex)
                {
                    status = NuGetOperationStatus.Failed;
                    uiService.ShowError(ex);
                }
                finally
                {
                    TelemetryServiceUtility.StopTimer();

                    var duration = TelemetryServiceUtility.GetTimerElapsedTime();

                    uiService.ProjectContext.Log(MessageLevel.Info,
                                                 string.Format(CultureInfo.CurrentCulture, Resources.Operation_TotalTime, duration));

                    uiService.EndOperation();

                    // don't show "Succeeded" if we actually cancelled...
                    if ((!continueAfterPreview) || (!acceptedLicense))
                    {
                        if (status == NuGetOperationStatus.Succeeded)
                        {
                            status = NuGetOperationStatus.Cancelled;
                        }
                    }

                    var plc = new PackageLoadContext(isSolution: false, uiService.UIContext);
                    IReadOnlyCollection <string> frameworks = await plc.GetSupportedFrameworksAsync();
                    string[] projectIds = (await ProjectUtility.GetSortedProjectIdsAsync(
                                               uiService.UIContext.ServiceBroker,
                                               uiService.Projects,
                                               cancellationToken)).ToArray();

                    var packageSourceMapping           = PackageSourceMapping.GetPackageSourceMapping(uiService.Settings);
                    bool isPackageSourceMappingEnabled = packageSourceMapping?.IsEnabled ?? false;
                    var actionTelemetryEvent           = new VSActionsTelemetryEvent(
                        uiService.ProjectContext.OperationId.ToString(),
                        projectIds,
                        operationType,
                        OperationSource.UI,
                        startTime,
                        status,
                        packageCount,
                        DateTimeOffset.Now,
                        duration.TotalSeconds,
                        isPackageSourceMappingEnabled: isPackageSourceMappingEnabled);

                    var nuGetUI = uiService as NuGetUI;
                    AddUiActionEngineTelemetryProperties(
                        actionTelemetryEvent,
                        continueAfterPreview,
                        acceptedLicense,
                        userAction,
                        nuGetUI?.SelectedIndex,
                        nuGetUI?.RecommendedCount,
                        nuGetUI?.RecommendPackages,
                        nuGetUI?.RecommenderVersion,
                        nuGetUI?.TopLevelVulnerablePackagesCount ?? 0,
                        nuGetUI?.TopLevelVulnerablePackagesMaxSeverities?.ToList() ?? new List <int>(),
                        existingPackages,
                        addedPackages,
                        removedPackages,
                        updatedPackagesOld,
                        updatedPackagesNew,
                        frameworks);

                    actionTelemetryEvent["InstalledPackageEnumerationTimeInMilliseconds"] = packageEnumerationTime.ElapsedMilliseconds;

                    TelemetryActivity.EmitTelemetryEvent(actionTelemetryEvent);
                }
            }, cancellationToken);
        }
Ejemplo n.º 17
0
        public override async Task <SearchResult <IPackageSearchMetadata> > ContinueSearchAsync(ContinuationToken continuationToken, CancellationToken cancellationToken)
        {
            var searchToken = continuationToken as FeedSearchContinuationToken;

            if (searchToken == null)
            {
                throw new InvalidOperationException("Invalid token");
            }

            if (_context != null)
            {
                _installedPackages = await _context.GetInstalledPackagesAsync();

                _context = null;
            }

            var packagesNeedingConsolidation = _installedPackages
                                               .GroupById()
                                               .Where(g => g.Count() > 1)
                                               .Select(g => new PackageIdentity(g.Key, g.Max()))
                                               .ToArray();

            var packages = packagesNeedingConsolidation
                           .Where(p => p.Id.IndexOf(searchToken.SearchString, StringComparison.OrdinalIgnoreCase) != -1)
                           .OrderBy(p => p.Id)
                           .Skip(searchToken.StartIndex)
                           .Take(PageSize + 1)
                           .ToArray();

            var hasMoreItems = packages.Length > PageSize;

            if (hasMoreItems)
            {
                packages = packages.Take(packages.Length - 1).ToArray();
            }

            var items = await TaskCombinators.ThrottledAsync(
                packages,
                (p, t) => _metadataProvider.GetPackageMetadataAsync(p, searchToken.SearchFilter.IncludePrerelease, t),
                cancellationToken);

            var result = SearchResult.FromItems(items.ToArray());

            var loadingStatus = hasMoreItems
                                ? LoadingStatus.Ready
                                : packages.Length == 0
                                ? LoadingStatus.NoItemsFound
                                : LoadingStatus.NoMoreItems;

            result.SourceSearchStatus = new Dictionary <string, LoadingStatus> {
                { "Consolidate", loadingStatus }
            };

            if (hasMoreItems)
            {
                result.NextToken = new FeedSearchContinuationToken {
                    SearchString = searchToken.SearchString,
                    SearchFilter = searchToken.SearchFilter,
                    StartIndex   = searchToken.StartIndex + packages.Length
                };
            }

            return(result);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// The internal implementation to perform user action.
        /// </summary>
        /// <param name="resolveActionsAsync">A function that returns a task that resolves the user
        /// action into project actions.</param>
        /// <param name="executeActionsAsync">A function that returns a task that executes
        /// the project actions.</param>
        private async Task PerformActionImplAsync(
            INuGetUI uiService,
            Func <SourceCacheContext, Task <IReadOnlyList <ResolvedAction> > > resolveActionsAsync,
            Func <IReadOnlyList <ResolvedAction>, SourceCacheContext, Task> executeActionsAsync,
            NuGetOperationType operationType,
            UserAction userAction,
            CancellationToken token)
        {
            var status       = NuGetOperationStatus.Succeeded;
            var startTime    = DateTimeOffset.Now;
            var packageCount = 0;

            bool continueAfterPreview = true;
            bool acceptedLicense      = true;

            List <string> removedPackages = null;
            HashSet <Tuple <string, string> > existingPackages   = new HashSet <Tuple <string, string> >();
            List <Tuple <string, string> >    addedPackages      = null;
            List <Tuple <string, string> >    updatedPackagesOld = null;
            List <Tuple <string, string> >    updatedPackagesNew = null;

            // Enable granular level telemetry events for nuget ui operation
            uiService.ProjectContext.OperationId = Guid.NewGuid();

            Stopwatch packageEnumerationTime = new Stopwatch();

            packageEnumerationTime.Start();
            try
            {
                // collect the install state of the existing packages
                foreach (var project in uiService.Projects)
                {
                    var result = await project.GetInstalledPackagesAsync(token);

                    foreach (var package in result)
                    {
                        Tuple <string, string> packageInfo = new Tuple <string, string>(package.PackageIdentity.Id, (package.PackageIdentity.Version == null ? "" : package.PackageIdentity.Version.ToNormalizedString()));
                        if (!existingPackages.Contains(packageInfo))
                        {
                            existingPackages.Add(packageInfo);
                        }
                    }
                }
            }
            catch (Exception)
            {
                // don't teardown the process if we have a telemetry failure
            }
            packageEnumerationTime.Stop();

            await _lockService.ExecuteNuGetOperationAsync(async() =>
            {
                try
                {
                    uiService.BeginOperation();

                    var acceptedFormat = await CheckPackageManagementFormat(uiService, token);
                    if (!acceptedFormat)
                    {
                        return;
                    }

                    TelemetryServiceUtility.StartOrResumeTimer();

                    using (var sourceCacheContext = new SourceCacheContext())
                    {
                        var actions = await resolveActionsAsync(sourceCacheContext);
                        var results = GetPreviewResults(actions);

                        if (operationType == NuGetOperationType.Uninstall)
                        {
                            // removed packages don't have version info
                            removedPackages = results.SelectMany(result => result.Deleted)
                                              .Select(package => package.Id)
                                              .Distinct()
                                              .ToList();
                            packageCount = removedPackages.Count;
                        }
                        else
                        {
                            // log rich info about added packages
                            addedPackages = results.SelectMany(result => result.Added)
                                            .Select(package => new Tuple <string, string>(package.Id, (package.Version == null ? "" : package.Version.ToNormalizedString())))
                                            .Distinct()
                                            .ToList();
                            var addCount = addedPackages.Count;

                            //updated packages can have an old and a new id.
                            updatedPackagesOld = results.SelectMany(result => result.Updated)
                                                 .Select(package => new Tuple <string, string>(package.Old.Id, (package.Old.Version == null ? "" : package.Old.Version.ToNormalizedString())))
                                                 .Distinct()
                                                 .ToList();
                            updatedPackagesNew = results.SelectMany(result => result.Updated)
                                                 .Select(package => new Tuple <string, string>(package.New.Id, (package.New.Version == null ? "" : package.New.Version.ToNormalizedString())))
                                                 .Distinct()
                                                 .ToList();
                            var updateCount = updatedPackagesNew.Count;

                            // update packages count
                            packageCount = addCount + updateCount;

                            if (updateCount > 0)
                            {
                                // set operation type to update when there are packages being updated
                                operationType = NuGetOperationType.Update;
                            }
                        }

                        TelemetryServiceUtility.StopTimer();

                        // Show the preview window.
                        if (uiService.DisplayPreviewWindow)
                        {
                            var shouldContinue = uiService.PromptForPreviewAcceptance(results);
                            if (!shouldContinue)
                            {
                                continueAfterPreview = false;
                                return;
                            }
                        }

                        TelemetryServiceUtility.StartOrResumeTimer();

                        // Show the license acceptance window.
                        var accepted = await CheckLicenseAcceptanceAsync(uiService, results, token);

                        TelemetryServiceUtility.StartOrResumeTimer();

                        if (!accepted)
                        {
                            acceptedLicense = false;
                            return;
                        }

                        // Warn about the fact that the "dotnet" TFM is deprecated.
                        if (uiService.DisplayDeprecatedFrameworkWindow)
                        {
                            var shouldContinue = ShouldContinueDueToDotnetDeprecation(uiService, actions, token);

                            TelemetryServiceUtility.StartOrResumeTimer();

                            if (!shouldContinue)
                            {
                                return;
                            }
                        }

                        if (!token.IsCancellationRequested)
                        {
                            // execute the actions
                            await executeActionsAsync(actions, sourceCacheContext);

                            // fires ActionsExecuted event to update the UI
                            uiService.OnActionsExecuted(actions);
                        }
                        else
                        {
                            status = NuGetOperationStatus.Cancelled;
                        }
                    }
                }
                catch (System.Net.Http.HttpRequestException ex)
                {
                    status = NuGetOperationStatus.Failed;
                    if (ex.InnerException != null)
                    {
                        uiService.ShowError(ex.InnerException);
                    }
                    else
                    {
                        uiService.ShowError(ex);
                    }
                }
                catch (Exception ex)
                {
                    status = NuGetOperationStatus.Failed;
                    uiService.ShowError(ex);
                }
                finally
                {
                    TelemetryServiceUtility.StopTimer();

                    var duration = TelemetryServiceUtility.GetTimerElapsedTime();

                    uiService.ProjectContext.Log(MessageLevel.Info,
                                                 string.Format(CultureInfo.CurrentCulture, Resources.Operation_TotalTime, duration));

                    uiService.EndOperation();

                    // don't show "Succeeded" if we actually cancelled...
                    if ((!continueAfterPreview) || (!acceptedLicense))
                    {
                        if (status == NuGetOperationStatus.Succeeded)
                        {
                            status = NuGetOperationStatus.Cancelled;
                        }
                    }

                    PackageLoadContext plc = new PackageLoadContext(sourceRepositories: null, isSolution: false, uiService.UIContext);
                    var frameworks         = plc.GetSupportedFrameworks().ToList();

                    var actionTelemetryEvent = VSTelemetryServiceUtility.GetActionTelemetryEvent(
                        uiService.ProjectContext.OperationId.ToString(),
                        uiService.Projects,
                        operationType,
                        OperationSource.UI,
                        startTime,
                        status,
                        packageCount,
                        duration.TotalSeconds);

                    var nuGetUI = uiService as NuGetUI;
                    AddUiActionEngineTelemetryProperties(
                        actionTelemetryEvent,
                        continueAfterPreview,
                        acceptedLicense,
                        userAction,
                        nuGetUI?.SelectedIndex,
                        nuGetUI?.RecommendedCount,
                        nuGetUI?.RecommendPackages,
                        nuGetUI?.RecommenderVersion,
                        existingPackages,
                        addedPackages,
                        removedPackages,
                        updatedPackagesOld,
                        updatedPackagesNew,
                        frameworks);

                    actionTelemetryEvent["InstalledPackageEnumerationTimeInMilliseconds"] = packageEnumerationTime.ElapsedMilliseconds;

                    TelemetryActivity.EmitTelemetryEvent(actionTelemetryEvent);
                }
            }, token);
        }
Ejemplo n.º 19
0
        public override async Task <SearchResult <IPackageSearchMetadata> > ContinueSearchAsync(ContinuationToken continuationToken, CancellationToken cancellationToken)
        {
            var searchToken = continuationToken as FeedSearchContinuationToken;

            if (searchToken == null)
            {
                throw new InvalidOperationException("Invalid token");
            }

            if (_context != null)
            {
                _installedPackages = await _context.GetInstalledPackagesAsync();

                _context = null;
            }

            var packages = _installedPackages
                           .GetLatest()
                           .Where(p => p.Id.IndexOf(searchToken.SearchString, StringComparison.OrdinalIgnoreCase) != -1)
                           .OrderBy(p => p.Id)
                           .Skip(searchToken.StartIndex)
                           .Take(PageSize + 1)
                           .ToArray();

            var hasMoreItems = packages.Length > PageSize;

            if (hasMoreItems)
            {
                packages = packages.Take(packages.Length - 1).ToArray();
            }

            var items = await TaskCombinators.ThrottledAsync(
                packages,
                (p, t) => GetPackageMetadataAsync (p, searchToken.SearchFilter.IncludePrerelease, t),
                cancellationToken);

            //  The packages were originally sorted which is important because we Skip and Take based on that sort
            //  however the asynchronous execution has randomly reordered the set. So we need to resort.
            var result = SearchResult.FromItems(items.OrderBy(p => p.Identity.Id).ToArray());

            var loadingStatus = hasMoreItems
                                ? LoadingStatus.Ready
                                : packages.Length == 0
                                ? LoadingStatus.NoItemsFound
                                : LoadingStatus.NoMoreItems;

            result.SourceSearchStatus = new Dictionary <string, LoadingStatus> {
                { "Installed", loadingStatus }
            };

            if (hasMoreItems)
            {
                result.NextToken = new FeedSearchContinuationToken {
                    SearchString = searchToken.SearchString,
                    SearchFilter = searchToken.SearchFilter,
                    StartIndex   = searchToken.StartIndex + packages.Length
                };
            }

            return(result);
        }