Esempio n. 1
0
        /// <summary>
        /// Search packages using the Chocolatey oData feed
        /// </summary>
        /// <param name="criteria"> The term to serach for</param>
        /// <returns></returns>
        public static IEnumerable <V2FeedPackage> Query(string criteria)
        {
            var feedClient = new FeedContext_x0060_1(Parameters.ChocoWebApiUri);
            var query      = feedClient.Packages.AddQueryOption("$filter", string.Format(Parameters.SearchOptionTemplate, criteria.ToLower()));

            return(query.Execute().ToList());
        }
        private RssActionResult RSS(Func<V1FeedPackage, bool> exclude)
        {
            var nugetODataUrl = new Uri("http://packages.nuget.org/v1/FeedService.svc");
            var nugetOData = new FeedContext_x0060_1(nugetODataUrl);

            var packages = nugetOData.Packages.OrderByDescending(p => p.Published);
            var nugetFeed = new List<SyndicationItem>();

            foreach (var package in packages)
            {
                if (exclude(package)) continue;

                var syndicationItem = new SyndicationItem(
                    package.Title,
                    package.Description,
                    new Uri(package.ProjectUrl ?? package.GalleryDetailsUrl),
                    package.Id,
                    package.LastUpdated);
                nugetFeed.Add(syndicationItem);
            }

            return new RssActionResult
            {
                Feed = new SyndicationFeed(
                    "NuGet Feed",
                    "NuGet OData feed converted to RSS",
                    new Uri("http://www.nugetfeed.com/"),
                    "urn:uuid:f4df456c-6643-4c53-a6e5-f180ce6e030d",
                    nugetFeed.First().LastUpdatedTime,
                    nugetFeed)
            };
        }
        private void timer_elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Stop();

            this.Log().Info(() => "Checking for submitted packages.");

            var submittedPackagesUri = NuGetService.get_service_endpoint_url(_configurationSettings.PackagesUrl, SERVICE_ENDPOINT);

            var service = new FeedContext_x0060_1(submittedPackagesUri);

            // this only returns 40 results at a time but at least we'll have something to start with
            //todo: This is going to only check where the flag automated validation is not true.
            IList <V2FeedPackage> submittedPackages = service.Packages.Where(p => p.PackageTestResultStatus == null || p.PackageTestResultStatus == "Pending" || p.PackageTestResultStatus == "Unknown").or_empty_list_if_null().ToList();

            this.Log().Info("Pulled {0} packages in submitted status for review.".format_with(submittedPackages.Count));

            foreach (var package in submittedPackages)
            {
                this.Log().Info("{0} found in submitted state.".format_with(package.Title));
                EventManager.publish(new SubmitPackageMessage(package.Id, package.Version));
            }

            this.Log().Info(() => "Finished checking for submitted packages.");

            _timer.Start();
        }
        private RssActionResult RSS(Func <V1FeedPackage, bool> exclude)
        {
            var nugetODataUrl = new Uri("http://packages.nuget.org/v1/FeedService.svc");
            var nugetOData    = new FeedContext_x0060_1(nugetODataUrl);

            var packages  = nugetOData.Packages.OrderByDescending(p => p.Published);
            var nugetFeed = new List <SyndicationItem>();

            foreach (var package in packages)
            {
                if (exclude(package))
                {
                    continue;
                }

                var syndicationItem = new SyndicationItem(
                    package.Title,
                    package.Description,
                    new Uri(package.ProjectUrl ?? package.GalleryDetailsUrl),
                    package.Id,
                    package.LastUpdated);
                nugetFeed.Add(syndicationItem);
            }

            return(new RssActionResult
            {
                Feed = new SyndicationFeed(
                    "NuGet Feed",
                    "NuGet OData feed converted to RSS",
                    new Uri("http://www.nugetfeed.com/"),
                    "urn:uuid:f4df456c-6643-4c53-a6e5-f180ce6e030d",
                    nugetFeed.First().LastUpdatedTime,
                    nugetFeed)
            });
        }
Esempio n. 5
0
        private static FeedContext_x0060_1 GetFeed(Uri source)
        {
            lock (FeedLockObject)
            {
                FeedContext_x0060_1 service;
                if ((service = (FeedContext_x0060_1)Cache.Get(GetMemoryCacheKey(source))) == null)
                {
                    service = new FeedContext_x0060_1(source)
                    {
                        IgnoreMissingProperties         = true,
                        IgnoreResourceNotFoundException = true,
                        MergeOption = MergeOption.NoTracking
                    };

                    Cache.Set(
                        GetMemoryCacheKey(source),
                        service,
                        new CacheItemPolicy {
                        SlidingExpiration = TimeSpan.FromMinutes(20)
                    });
                }

                return(service);
            }
        }
        private void timer_elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Stop();

            this.Log().Info(() => "Checking for submitted packages.");

            var submittedPackagesUri = NuGetService.get_service_endpoint_url(_configurationSettings.PackagesUrl, SERVICE_ENDPOINT);

            var service = new FeedContext_x0060_1(submittedPackagesUri);

            // this only returns 40 results at a time but at least we'll have something to start with
            //todo: This is going to only check where the flag automated validation is not true.
            IList<V2FeedPackage> submittedPackages = service.Packages.Where(p => p.PackageTestResultStatus == null || p.PackageTestResultStatus == "Pending" || p.PackageTestResultStatus == "Unknown").or_empty_list_if_null().ToList();

            this.Log().Info("Pulled {0} packages in submitted status for review.".format_with(submittedPackages.Count));

            foreach (var package in submittedPackages)
            {
                this.Log().Info("{0} found in submitted state.".format_with(package.Title));
                EventManager.publish(new SubmitPackageMessage(package.Id, package.Version));
            }

            this.Log().Info(() => "Finished checking for submitted packages.");

            _timer.Start();
        }
        private void timer_elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Stop();

            this.Log().Info(() => "Checking for packages to validate.");

            try
            {
                var submittedPackagesUri = NuGetService.get_service_endpoint_url(_configurationSettings.PackagesUrl, SERVICE_ENDPOINT);

                // such a fun, dynamically generated name
                var service = new FeedContext_x0060_1(submittedPackagesUri)
                {
                    Timeout = 70
                };

                var cdnCacheTimeout = DateTime.UtcNow.AddMinutes(-31);
                // this only returns 30-40 results at a time but at least we'll have something to start with
                IQueryable <V2FeedPackage> packageQuery =
                    service.Packages.Where(
                        p => p.Created < cdnCacheTimeout &&
                        (p.PackageValidationResultStatus == null || p.PackageValidationResultStatus == "Pending" || p.PackageValidationResultStatus == "Unknown")
                        );

                // specifically reduce the call to 30 results so we get back results faster from Chocolatey.org
                IList <V2FeedPackage> packagesToValidate = packageQuery.Take(30).ToList();
                if (packagesToValidate.Count == 0)
                {
                    this.Log().Info("No packages to validate.");
                }
                else
                {
                    this.Log().Info("Pulled in {0} packages for validation.".format_with(packagesToValidate.Count));
                }

                foreach (var package in packagesToValidate.or_empty_list_if_null())
                {
                    this.Log().Info(() => "========== {0} v{1} ==========".format_with(package.Id, package.Version));
                    this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                    EventManager.publish(new ValidatePackageMessage(package.Id, package.Version));
                }
            }
            catch (Exception ex)
            {
                Bootstrap.handle_exception(ex);
            }

            this.Log().Info(() => "Finished checking for packages to validate. Sleeping for {0} minute(s).".format_with(TIMER_INTERVAL / 60000));

            _timer.Start();
        }
Esempio n. 8
0
        public static async Task <Exception> TestPath(Uri source)
        {
            try
            {
                var service = new FeedContext_x0060_1(source);
                var query   = (DataServiceQuery <V2FeedPackage>)service.Packages.Take(1);
                var result  = query.FirstOrDefault();
                await Task.Factory.FromAsync(query.BeginExecute, ar => query.EndExecute(ar), null);

                return(null);
            }
            catch (Exception ex)
            {
                return(ex);
            }
        }
Esempio n. 9
0
        public static PackageQueryResult GetUpdates(ContextName context, string nuGetSite, PackageStability stability, IEnumerable <IPackageId> ids)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (nuGetSite == null)
            {
                throw new ArgumentNullException("nuGetSite");
            }
            if (ids == null)
            {
                throw new ArgumentNullException("ids");
            }

            using (var contextKey = PackageRegistry.OpenRegistryRoot(false, context))
            {
                var service = new FeedContext_x0060_1(new Uri(nuGetSite));

                var query = service.CreateQuery <V2FeedPackage>("GetUpdates")
                            .AddQueryOption("packageIds", "'" + String.Join("|", ids.Select(p => p.Id)) + "'")
                            .AddQueryOption("versions", "'" + String.Join("|", ids.Select(p => p.Version)) + "'")
                            .AddQueryOption("includePrerelease", (stability == PackageStability.IncludePrerelease) ? "true" : "false")
                            .AddQueryOption("includeAllVersions", "false");

                var response = (QueryOperationResponse <V2FeedPackage>)query.Execute();

                var packageMetadatas = response.Select(p => Deserialize(p, context, contextKey, nuGetSite)).ToArray();

                return(new PackageQueryResult(
                           GetTotalCount(response, packageMetadatas),
                           0,
                           1,
                           packageMetadatas
                           ));
            }
        }
Esempio n. 10
0
        private void timer_elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Stop();

            this.Log().Info(() => "Checking for packages to verify.");

            try
            {
                var submittedPackagesUri = NuGetService.get_service_endpoint_url(_configurationSettings.PackagesUrl, ServiceEndpoint);

                var lastPackage = string.Empty;

                //for (var i = 0; i < 10; i++)
                //{
                this.Log().Info(() => "Grabbing next available package for verification.");

                var service = new FeedContext_x0060_1(submittedPackagesUri)
                {
                    Timeout = 70
                };

                var cacheTimeout = DateTime.UtcNow.AddMinutes(-31);
                // this only returns 40 results at a time but at least we'll have something to start with
                IQueryable <V2FeedPackage> packageQuery =
                    service.Packages.Where(p => p.Created < cacheTimeout);

                if (AdditionalPackageSelectionFilters != null)
                {
                    packageQuery = AdditionalPackageSelectionFilters.Invoke(packageQuery);
                }

                //int total = packageQuery.Count();
                //packageQuery = packageQuery.Where(p => p.Id == "");

                packageQuery = packageQuery.OrderBy(p => p.Created);

                // let's specifically reduce the call to 30 results so we get back results faster from Chocolatey.org
                IList <V2FeedPackage> packagesToValidate = packageQuery.Take(30).ToList();

                if (packagesToValidate.Count == 0)
                {
                    this.Log().Info("No packages to verify.");
                    //break;
                }

                //remove the random for now, we'll just grab the top result
                //this.Log().Info("Pulled in {0} packages, picking one at random to verify.".format_with(packagesToValidate.Count));

                //var skip = new Random().Next(packagesToValidate.Count);
                //if (skip < 0) skip = 0;
                //packagesToValidate = packagesToValidate.Skip(skip).Take(1).ToList();

                //var package = packagesToValidate.FirstOrDefault();
                //if (package == null) continue;

                //var packageId = "{0}:{1}".format_with(package.Id, package.Version);
                //if (lastPackage == packageId)
                //{
                //    this.Log().Info("Already verified {0} v{1} recently.".format_with(package.Title, package.Version));
                //    continue;
                //}
                //lastPackage = packageId;

                //this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                //EventManager.publish(new VerifyPackageMessage(package.Id, package.Version));

                foreach (var package in packagesToValidate.or_empty_list_if_null())
                {
                    this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                    EventManager.publish(new VerifyPackageMessage(package.Id, package.Version));
                }
                // }
            }
            catch (Exception ex)
            {
                Bootstrap.handle_exception(ex);
            }

            this.Log().Info(() => "Finished checking for packages to verify. Sleeping for {0} minutes.".format_with(TIMER_INTERVAL / 60000));

            _timer.Start();
        }
Esempio n. 11
0
        private List <PackageViewModel> GeneratePackages(string file)
        {
            Debug.WriteLine($"Processing {file}.");

            var packages    = new List <PackageViewModel>();
            var feedContext = new FeedContext_x0060_1(new Uri(RepositoryUrl))
            {
                IgnoreMissingProperties = true
            };

            ApplyCredentials(feedContext);

            var packagesConfig = XDocument.Load(file);
            var dependencies   = new List <DependencyViewModel>();

            if (Path.GetFileName(file).Equals("packages.config", StringComparison.CurrentCultureIgnoreCase))
            {
                foreach (var package in packagesConfig.Descendants("package"))
                {
                    var id      = package.Attribute("id").Value;
                    var version = package.Attribute("version").Value;
                    // ReSharper disable ReplaceWithSingleCallToFirstOrDefault
                    var remotePackage =
                        feedContext
                        .Packages
                        .OrderByDescending(x => x.Version)
                        .Where(x => x.Id == id && x.IsLatestVersion && !x.IsPrerelease)
                        .FirstOrDefault();
                    // ReSharper restore ReplaceWithSingleCallToFirstOrDefault

                    dependencies.Add(new DependencyViewModel {
                        NugetId = id, Version = version
                    });

                    if (remotePackage == null)
                    {
                        continue;
                    }

                    if (packages.Any(p => p.NugetId == id && p.LocalVersion == version))
                    {
                        continue;
                    }

                    packages.Add(
                        new PackageViewModel
                    {
                        RemoteVersion = remotePackage.Version,
                        LocalVersion  = version,
                        NugetId       = id,
                        Id            = Guid.NewGuid().ToString(),
                        Dependencies  = remotePackage.Dependencies
                                        .Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries)
                                        .Select(
                            x =>
                        {
                            var strings = x.Split(new[] { ':' });

                            return(new DependencyViewModel {
                                NugetId = strings[0], Version = strings[1]
                            });
                        })
                                        .ToArray()
                    });

                    foreach (
                        var pack in
                        packages
                        .Last()
                        .Dependencies
                        .Select(
                            dependency =>
                            dependencies
                            .FirstOrDefault(
                                x => x.NugetId == dependency.NugetId && x.Version == dependency.Version))
                        .Where(pack => pack != null))
                    {
                        dependencies.Remove(pack);
                    }
                }
            }

            if (Path.GetExtension(file).Equals(".csproj", StringComparison.CurrentCultureIgnoreCase))
            {
                //todo process new format CSProj file.  <PackageReference Include="Microsoft.TeamFoundation.DistributedTask.Common" version="15.112.1" />
                foreach (var package in packagesConfig.Descendants("PackageReference"))
                {
                    var id      = package.Attribute("Include")?.Value;
                    var version = package.Attribute("Version")?.Value;
                    // ReSharper disable ReplaceWithSingleCallToFirstOrDefault
                    var remotePackage =
                        feedContext
                        .Packages
                        .OrderByDescending(x => x.Version)
                        .Where(x => x.Id == id && x.IsLatestVersion && !x.IsPrerelease)
                        .FirstOrDefault();
                    // ReSharper restore ReplaceWithSingleCallToFirstOrDefault

                    dependencies.Add(new DependencyViewModel {
                        NugetId = id, Version = version
                    });

                    if (remotePackage == null)
                    {
                        continue;
                    }

                    if (packages.Any(p => p.NugetId == id && p.LocalVersion == version))
                    {
                        continue;
                    }

                    packages.Add(
                        new PackageViewModel
                    {
                        RemoteVersion = remotePackage.Version,
                        LocalVersion  = version,
                        NugetId       = id,
                        Id            = Guid.NewGuid().ToString(),
                        Dependencies  = remotePackage.Dependencies
                                        .Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries)
                                        .Select(
                            x =>
                        {
                            var strings = x.Split(new[] { ':' });

                            return(new DependencyViewModel {
                                NugetId = strings[0], Version = strings[1]
                            });
                        })
                                        .ToArray()
                    });

                    foreach (
                        var pack in
                        packages
                        .Last()
                        .Dependencies
                        .Select(
                            dependency =>
                            dependencies
                            .FirstOrDefault(
                                x => x.NugetId == dependency.NugetId && x.Version == dependency.Version))
                        .Where(pack => pack != null))
                    {
                        dependencies.Remove(pack);
                    }
                }
            }

            packages.Add(
                new PackageViewModel
            {
                RemoteVersion = "",
                LocalVersion  = "",
                NugetId       = Path.GetFileName(Path.GetDirectoryName(file)),
                Id            = Guid.NewGuid().ToString(),
                Dependencies  = dependencies.ToArray()
            });

            return(packages);
        }
Esempio n. 12
0
        private void timer_elapsed(object sender, ElapsedEventArgs e)
        {
            _timer.Stop();

            this.Log().Info(() => "Checking for packages to cleanup (remind/reject).");

            try
            {
                var submittedPackagesUri = NuGetService.get_service_endpoint_url(_configurationSettings.PackagesUrl, SERVICE_ENDPOINT);

                // such a fun, dynamically generated name
                var service = new FeedContext_x0060_1(submittedPackagesUri)
                {
                    Timeout = 70
                };

                var twentyDaysAgo = DateTime.UtcNow.AddDays(-20);

                // this only returns 30-40 results at a time but at least we'll have something to start with

                //this is not a perfect check but will capture most of the items that need cleaned up.
                IQueryable <V2FeedPackage> packageQuery =
                    service.Packages.Where(
                        p => p.Created < twentyDaysAgo &&
                        p.PackageStatus == "Submitted" &&
                        p.PackageSubmittedStatus == "Waiting" &&
                        (p.PackageCleanupResultDate == null) &&
                        ((p.PackageReviewedDate != null && p.PackageReviewedDate < twentyDaysAgo)
                         ||
                         (p.PackageReviewedDate == null && p.PackageTestResultStatusDate < twentyDaysAgo)
                        )
                        );

                //int totalCount = packageQuery.Count();

                // specifically reduce the call to 30 results so we get back results faster from Chocolatey.org
                IList <V2FeedPackage> packages = packageQuery.Take(30).ToList();
                if (packages.Count == 0)
                {
                    this.Log().Info("No packages to remind.");
                }
                else
                {
                    this.Log().Info("Pulled in {0} packages for reminders.".format_with(packages.Count));
                }

                foreach (var package in packages.or_empty_list_if_null())
                {
                    this.Log().Info(() => "========== {0} v{1} ==========".format_with(package.Id, package.Version));
                    this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                    EventManager.publish(new ReminderPackageMessage(package.Id, package.Version));
                }

                var fifteenDaysAgo = DateTime.UtcNow.AddDays(-15);
                IQueryable <V2FeedPackage> packageQueryForReject =
                    service.Packages.Where(
                        p => p.PackageCleanupResultDate < fifteenDaysAgo &&
                        p.PackageStatus == "Submitted" &&
                        p.PackageSubmittedStatus == "Waiting"
                        );

                // specifically reduce the call to 30 results so we get back results faster from Chocolatey.org
                IList <V2FeedPackage> packagesForReject = packageQueryForReject.Take(30).ToList();
                if (packagesForReject.Count == 0)
                {
                    this.Log().Info("No packages to reject.");
                }
                else
                {
                    this.Log().Info("Pulled in {0} packages for rejection.".format_with(packages.Count));
                }

                foreach (var package in packagesForReject.or_empty_list_if_null())
                {
                    this.Log().Info(() => "========== {0} v{1} ==========".format_with(package.Id, package.Version));
                    this.Log().Info("{0} v{1} found for review.".format_with(package.Title, package.Version));
                    EventManager.publish(new RejectPackageMessage(package.Id, package.Version));
                }
            }
            catch (Exception ex)
            {
                Bootstrap.handle_exception(ex);
            }

            this.Log().Info(() => "Finished checking for packages to cleanup. Sleeping for {0} minute(s).".format_with(TIMER_INTERVAL / 60000));

            _timer.Start();
        }
Esempio n. 13
0
        private static PackageQueryResult Query(ContextName context, string nuGetSite, IList <string> packageIds, PackageStability stability, PackageQueryOrder queryOrder, int?page)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (nuGetSite == null)
            {
                throw new ArgumentNullException("nuGetSite");
            }

            var service = new FeedContext_x0060_1(new Uri(nuGetSite));

            IQueryable <V2FeedPackage> query = service.Packages
                                               .IncludeTotalCount()
                                               .Where(p =>
                                                      p.IsAbsoluteLatestVersion &&
                                                      p.IsLatestVersion
                                                      );

            if (packageIds != null)
            {
                if (packageIds.Count == 0)
                {
                    throw new ArgumentOutOfRangeException("packageIds");
                }

                // The feed doesn't support contains. Because of this, we're
                // building the ||'s of all ID's here dynamically.

                var idProperty          = typeof(V2FeedPackage).GetProperty("Id");
                var parameterExpression = Expression.Parameter(typeof(V2FeedPackage), "p");

                Expression predicate = null;

                foreach (string id in packageIds)
                {
                    var thisPredicate = Expression.Equal(
                        Expression.Property(parameterExpression, idProperty),
                        Expression.Constant(id)
                        );

                    predicate =
                        predicate == null
                        ? thisPredicate
                        : Expression.OrElse(predicate, thisPredicate);
                }

                query = query.Where(Expression.Lambda <Func <V2FeedPackage, bool> >(
                                        predicate, new[] { parameterExpression }
                                        ));
            }
            else
            {
                string prefix = context.Name + ".Package.";

                query = query.Where(p =>
                                    p.Id.StartsWith(prefix) ||
                                    p.Id.StartsWith("NetIde.Package.")
                                    );
            }

            if (stability == PackageStability.StableOnly)
            {
                query = query.Where(p => !p.IsPrerelease);
            }

            switch (queryOrder)
            {
            case PackageQueryOrder.MostDownloads:
                query = query.OrderByDescending(p => p.DownloadCount);
                break;

            case PackageQueryOrder.PublishedDate:
                query = query.OrderByDescending(p => p.Published);
                break;

            case PackageQueryOrder.NameAscending:
                query = query.OrderBy(p => p.Title);
                break;

            case PackageQueryOrder.NameDescending:
                query = query.OrderByDescending(p => p.Title);
                break;
            }

            if (page.HasValue)
            {
                if (page.Value > 0)
                {
                    query = query.Skip(page.Value * PageCount);
                }

                query = query.Take(PageCount);
            }

            var response = (QueryOperationResponse <V2FeedPackage>)((DataServiceQuery <V2FeedPackage>)query).Execute();

            using (var contextKey = PackageRegistry.OpenRegistryRoot(false, context))
            {
                return(new PackageQueryResult(
                           response.TotalCount,
                           page.GetValueOrDefault(0),
                           (int)((response.TotalCount / PageCount) + 1),
                           response.Select(p => Deserialize(p, context, contextKey, nuGetSite)).ToArray()
                           ));
            }
        }
Esempio n. 14
0
        public static PackageMetadata ResolvePackageVersion(ContextName context, string nuGetSite, string packageId, string versionRestriction, PackageStability stability)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (nuGetSite == null)
            {
                throw new ArgumentNullException("nuGetSite");
            }
            if (packageId == null)
            {
                throw new ArgumentNullException("packageId");
            }
            if (versionRestriction == null)
            {
                throw new ArgumentNullException("versionRestriction");
            }

            string installedVersion = PackageManager.GetInstalledVersion(context, packageId);

            if (installedVersion == null)
            {
                // This method is used to resolve dependencies. If we don't
                // have the package installed, we check whether it's a valid
                // package ID at all. If not, the dependency probably is an
                // invalid dependency (or the NetIde.Runtime dependency)
                // and we completely ignore it.

                if (!PackageManager.IsValidPackageId(context, packageId))
                {
                    return(null);
                }

                // We default to 0.0.0.0 for uninstalled packages. This could
                // give issues when the package available in NuGet has
                // version 0.0.0.0. The only way to use this API is to provide
                // a valid version number, so this currently is a limitation,
                // i.e. that you can't have NuGet packages of version 0.0.0.0.

                installedVersion = "0.0.0.0";
            }

            var service = new FeedContext_x0060_1(new Uri(nuGetSite));

            var query = service.CreateQuery <V2FeedPackage>("GetUpdates")
                        .AddQueryOption("packageIds", "'" + packageId + "'")
                        .AddQueryOption("versions", "'" + installedVersion + "'")
                        .AddQueryOption("includePrerelease", (stability == PackageStability.IncludePrerelease) ? "true" : "false")
                        .AddQueryOption("includeAllVersions", "false")
                        .AddQueryOption("versionConstraints", "'" + versionRestriction + "'");

            var response = (QueryOperationResponse <V2FeedPackage>)query.Execute();

            PackageMetadata[] packages;

            using (var contextKey = PackageRegistry.OpenRegistryRoot(false, context))
            {
                packages = response.Select(p => Deserialize(p, context, contextKey, nuGetSite)).ToArray();
            }

            Debug.Assert(packages.Length <= 1);

            if (packages.Length > 0)
            {
                return(packages[0]);
            }

            return(null);
        }