Example #1
0
        private static void NormalizeVersion(NuGetRequest request, ref string requiredVersion, ref string minimumVersion, ref string maximumVersion) {
            if (!string.IsNullOrWhiteSpace(requiredVersion))
            {
                requiredVersion = requiredVersion.FixVersion();
                minimumVersion = null;
                maximumVersion = null;
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(minimumVersion))
                {
                    minimumVersion = minimumVersion.FixVersion();
                }

                if (!string.IsNullOrWhiteSpace(maximumVersion))
                {
                    maximumVersion = maximumVersion.FixVersion();
                }
            }

            if (!string.IsNullOrWhiteSpace(minimumVersion) && !string.IsNullOrWhiteSpace(maximumVersion))
            {
                if(new SemanticVersion(minimumVersion) > new SemanticVersion(maximumVersion))
                {
                    request.Warning("Specified version range is invalid. minimumVersion = {0} maximumVersion ={1}", minimumVersion, maximumVersion);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Searches package sources given name and version information
        ///
        /// Package information must be returned using <c>request.YieldPackage(...)</c> function.
        /// </summary>
        /// <param name="name">a name or partial name of the package(s) requested</param>
        /// <param name="requiredVersion">A specific version of the package. Null or empty if the user did not specify</param>
        /// <param name="minimumVersion">A minimum version of the package. Null or empty if the user did not specify</param>
        /// <param name="maximumVersion">A maximum version of the package. Null or empty if the user did not specify</param>
        /// <param name="id">if this is greater than zero (and the number should have been generated using <c>StartFind(...)</c>, the core is calling this multiple times to do a batch search request. The operation can be delayed until <c>CompleteFind(...)</c> is called</param>
        /// <param name="request">An object passed in from the PackageManagement that contains functions that can be used to interact with its Provider</param> 
        public void FindPackage(string name, string requiredVersion, string minimumVersion, string maximumVersion, int id, NuGetRequest request)
        {
            if (request == null){
                throw new ArgumentNullException("request");
            }

            // true if we want to include the max and min version
            bool minInclusive = true;
            bool maxInclusive = true;

            // If finding by canonical id, then the version follows dependency version requirement
            if (request.GetOptionValue("FindByCanonicalId").IsTrue())
            {
                // Use the dependency version if no min and max is supplied
                if (String.IsNullOrWhiteSpace(maximumVersion) && String.IsNullOrWhiteSpace(minimumVersion))
                {
                    DependencyVersion depVers = DependencyVersion.ParseDependencyVersion(requiredVersion);
                    maximumVersion = depVers.MaxVersion.ToStringSafe();
                    minimumVersion = depVers.MinVersion.ToStringSafe();
                    minInclusive = depVers.IsMinInclusive;
                    maxInclusive = depVers.IsMaxInclusive;

                    // set required version if we have both min max as the same value.
                    if (depVers.MaxVersion != null && depVers.MinVersion != null
                        && depVers.MaxVersion == depVers.MinVersion && minInclusive && maxInclusive)
                    {
                        requiredVersion = maximumVersion;
                    }
                    else
                    {
                        requiredVersion = null;
                    }
                }                
            }

            request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, string.Format(CultureInfo.InvariantCulture, "FindPackage' - name='{0}', requiredVersion='{1}',minimumVersion='{2}', maximumVersion='{3}'", name, requiredVersion, minimumVersion, maximumVersion));

            NormalizeVersion(request, ref requiredVersion, ref minimumVersion, ref maximumVersion);

            try {

            
            // If there are any packages, yield and return
            if (request.YieldPackages(request.GetPackageById(name, request, requiredVersion, minimumVersion, maximumVersion, minInclusive, maxInclusive), name))
            {
                return;
            }

            // Check if the name contains wildcards. If not, return. This matches the behavior as "Get-module xje" 
            if (!String.IsNullOrWhiteSpace(name) && !WildcardPattern.ContainsWildcardCharacters(name))
            {              
                return;
            }

            // In the case of the package name is null or contains wildcards, error out if a user puts version info
            if (!String.IsNullOrWhiteSpace(requiredVersion) || !String.IsNullOrWhiteSpace(minimumVersion) || !String.IsNullOrWhiteSpace(maximumVersion))
            {
                request.Warning( Constants.Messages.MissingRequiredParameter, "name");
                return;
            }
            
            
       
            // Have we been cancelled?
            if (request.IsCanceled) {
                request.Debug(Resources.Messages.RequestCanceled, PackageProviderName, "FindPackage");

                return;
            }

            // A user does not provide the package full Name at all Or used wildcard in the name. Let's try searching the entire repository for matches.
            request.YieldPackages(request.SearchForPackages(name), name);
            }
            catch (Exception ex)
            {
                ex.Dump(request);
            }
        }
Example #3
0
        /// <summary>
        /// Returns the packages that are installed. This method is called when a user type get-package, install-package and uninstall-package.
        /// </summary>
        /// <param name="name">the package name to match. Empty or null means match everything</param>
        /// <param name="requiredVersion">the specific version asked for. If this parameter is specified (ie, not null or empty string) then the minimum and maximum values are ignored</param>
        /// <param name="minimumVersion">the minimum version of packages to return . If the <code>requiredVersion</code> parameter is specified (ie, not null or empty string) this should be ignored</param>
        /// <param name="maximumVersion">the maximum version of packages to return . If the <code>requiredVersion</code> parameter is specified (ie, not null or empty string) this should be ignored</param>
        /// <param name="request">An object passed in from the PackageManagement that contains functions that can be used to interact with its Provider</param> 
        public void GetInstalledPackages(string name, string requiredVersion, string minimumVersion, string maximumVersion, NuGetRequest request) 
        {
            if (request == null){
                throw new ArgumentNullException("request");
            }

            request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, string.Format(CultureInfo.InvariantCulture, "GetInstalledPackages' - name='{0}', requiredVersion='{1}',minimumVersion='{2}', maximumVersion='{3}'", name, requiredVersion, minimumVersion, maximumVersion));

            // In the case of the package name is null or contains wildcards, error out if a user puts version info
            if (!String.IsNullOrWhiteSpace(requiredVersion) || !String.IsNullOrWhiteSpace(minimumVersion) || !String.IsNullOrWhiteSpace(maximumVersion))
            {
                // A user provides the version info but missing name
                if (string.IsNullOrWhiteSpace(name))
                {
                    request.Warning(Constants.Messages.MissingRequiredParameter, "name");
                    return;
                }

                // A user provides the version info but the name containing wildcards
                if (WildcardPattern.ContainsWildcardCharacters(name)) {
                    return;
                }
            }

            NormalizeVersion(request, ref requiredVersion, ref minimumVersion, ref maximumVersion);

            request.GetInstalledPackages(name, requiredVersion, minimumVersion, maximumVersion);
        }
        /// <summary>
        /// Send the request to the server with buffer size to account for the case where there are more data
        /// that we need to fetch
        /// </summary>
        /// <param name="query"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public static IEnumerable<PackageBase> SendRequest(string query, NuGetRequest request)
        {
            const int bufferSize = 40;
            // number of threads sending the requests
            const int numberOfSenders = 4;

            var startPoint = 0;
            var tasks = new List<Task<Stream>>();

            bool stopSending = false;
            object stopLock = new Object();

            // Send one request first

            // this initial query is of the form http://www.nuget.org/api/v2/FindPackagesById()?id='jquery'&$skip={0}&$top={1}
            UriBuilder initialQuery = new UriBuilder(query.InsertSkipAndTop());

            PackageBase firstPackage = null;

            // Send out an initial request
            // we send out 1 initial request first to check for redirection and check whether repository supports odata
            using (Stream stream = NuGetClient.InitialDownloadDataToStream(initialQuery, startPoint, bufferSize, request))
            {
                if (stream == null)
                {
                    yield break;
                }

                XDocument document = XmlUtility.LoadSafe(stream, ignoreWhiteSpace: true);

                var entries = document.Root.ElementsNoNamespace("entry").ToList();

                // If the initial request has different number of entries than the buffer size, return it because this means the server
                // does not understand odata request or there is no more data. in the former case, we have to stop to prevent infinite loop
                if (entries.Count != bufferSize)
                {
                    request.Debug(Messages.PackagesReceived, entries.Count);
                    stopSending = true;
                }

                foreach (XElement entry in entries)
                {
                    var package = new PackageBase();

                    // set the first package of the request. this is used later to verify that the case when the number of packages in the repository
                    // is the same as the buffer size and the repository does not support odata query. in that case, we want to check whether the first package
                    // exists anywhere in the second call. if it is, then we cancel the request (this is to prevent infinite loop)
                    if (firstPackage == null)
                    {
                        firstPackage = package;
                    }

                    PackageUtility.ReadEntryElement(ref package, entry);
                    yield return package;
                }
            }

            if (stopSending || request.IsCanceled)
            {
                yield break;
            }

            // To avoid more redirection (for example, if the initial query is nuget.org, it will be changed to www.nuget.org

            query = initialQuery.Uri.ToString();

            // Sending the initial requests
            for (var i = 0; i < numberOfSenders; i++)
            {
                // Update the start point to fetch the packages
                startPoint += bufferSize;

                // Get the query
                var newQuery = string.Format(query, startPoint, bufferSize);

                // Send it
                tasks.Add(Task.Factory.StartNew(() =>
                {
                    Stream items = NuGetClient.DownloadDataToStream(newQuery, request);
                    return items;
                }));
            }

            //Wait for the responses, parse the data, and send to the user
            while (tasks.Count > 0)
            {

                //Cast because the compiler warning: Co-variant array conversion from Task[] to Task[] can cause run-time exception on write operation.
                var index = Task.WaitAny(tasks.Cast<Task>().ToArray());

                using (Stream stream = tasks[index].Result)
                {
                    if (stream == null)
                    {
                        yield break;
                    }

                    XDocument document = XmlUtility.LoadSafe(stream, ignoreWhiteSpace: true);

                    var entries = document.Root.ElementsNoNamespace("entry").ToList();

                    if (entries.Count < bufferSize)
                    {
                        request.Debug(Messages.PackagesReceived, entries.Count);
                        lock (stopLock)
                        {
                            stopSending = true;
                        }
                    }

                    foreach (XElement entry in entries)
                    {
                        var package = new PackageBase();

                        PackageUtility.ReadEntryElement(ref package, entry);

                        if (firstPackage != null)
                        {
                            // check whether first package in the first request exists anywhere in the second request
                            if (string.Equals(firstPackage.GetFullName(), package.GetFullName(), StringComparison.OrdinalIgnoreCase)
                                && string.Equals(firstPackage.Version, package.Version, StringComparison.OrdinalIgnoreCase))
                            {
                                lock (stopLock)
                                {
                                    stopSending = true;
                                }

                                break;
                            }
                        }

                        yield return package;
                    }

                    // we only needs to check for the existence of the first package in the second request. don't need to do for subsequent request
                    if (firstPackage != null)
                    {
                        firstPackage = null;
                    }
                }

                // checks whether we should stop sending requests
                if (!stopSending && !request.IsCanceled)
                {
                    // Make sure nobody else is updating the startPoint
                    lock (stopLock)
                    {
                        // update the startPoint
                        startPoint += bufferSize;
                    }
                    // Make a new request with the new startPoint
                    var newQuery = string.Format(query, startPoint, bufferSize);

                    //Keep sending a request
                    tasks[index] = (Task.Factory.StartNew(searchQuery =>
                    {
                        var items = NuGetClient.DownloadDataToStream(searchQuery.ToStringSafe(), request);
                        return items;
                    }, newQuery));

                }
                else
                {
                    if (request.IsCanceled)
                    {
                        request.Warning(Messages.RequestCanceled, "HttpClientPackageRepository", "SendRequest");
                        //stop sending request to the remote server
                        stopSending = true;
                    }

                    tasks.RemoveAt(index);
                }
            }
        }
Example #5
0
        /// <summary>
        /// Removes/Unregisters a package source
        /// </summary>
        /// <param name="name">The name or location of a package source to remove.</param>
        /// <param name="request">An object passed in from the PackageManagement that contains functions that can be used to interact with its Provider</param> 
        public void RemovePackageSource(string name, NuGetRequest request)
        {
            if (request == null){
                throw new ArgumentNullException("request");
            }
            request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, "RemovePackageSource");

            var src = request.FindRegisteredSource(name);
            if (src == null)
            {
                request.Warning(Constants.Messages.UnableToResolveSource, name);
                return;
            }

            request.RemovePackageSource(src.Name);
            request.YieldPackageSource(src.Name, src.Location, src.Trusted, false, src.IsValidated);
        }
        /// <summary>
        ///     Removes/Unregisters a package source
        /// </summary>
        /// <param name="name">The name or location of a package source to remove.</param>
        /// <param name="request">
        ///     An object passed in from the CORE that contains functions that can be used to interact with the
        ///     CORE and HOST
        /// </param>
        public void RemovePackageSource(string name, NuGetRequest request)
        {
            // Nice-to-have put a debug message in that tells what's going on.
            request.Debug("Calling '{0}::RemovePackageSource' '{1}'", PackageProviderName, name);

            var src = request.FindRegisteredSource(name);
            if (src == null) {
                request.Warning(Constants.Messages.UnableToResolveSource, name);
                return;
            }

            request.RemovePackageSource(src.Name);
            request.YieldPackageSource(src.Name, src.Location, src.Trusted, false, src.IsValidated);
        }
        /// <summary>
        /// Download data from remote via uri query.
        /// </summary>
        /// <param name="fileName">A file to store the downloaded data.</param>
        /// <param name="query">Uri query</param>
        /// <param name="request">An object passed in from the PackageManagement platform that contains APIs that can be used to interact with it </param>   
        /// <returns></returns>
        internal static async Task<long> DownloadDataToFileAsync(string fileName, string query, NuGetRequest request)
        {
            request.Verbose(Messages.DownloadingPackage, query);

            var client = GetHttpClient(request);

            var response = PathUtility.GetHttpResponse(client, query, request);

            // Check that response was successful or write error
            if (response == null || !response.IsSuccessStatusCode)
            {
                request.Warning(Resources.Messages.CouldNotGetResponseFromQuery, query);
                return 0;
            }

            // Check that response was successful or throw exception
            response.EnsureSuccessStatusCode();

            // Read response asynchronously and write out a file
            // The return value is for the caller to wait for the async operation to complete.
            var fileLength = await response.Content.ReadAsFileAsync(fileName);

            request.Verbose(Messages.CompletedDownload, query);

            return fileLength;
        }
        /// <summary>
        /// Download a nuget package.
        /// </summary>
        /// <param name="packageName">Package name</param>
        /// <param name="version">Package version</param>
        /// <param name="destination">Destination location to store the downloaded package</param>
        /// <param name="queryUrl">Uri to query the package</param>
        /// <param name="request">An object passed in from the PackageManagement platform that contains APIs that can be used to interact with it </param>   
        internal static void DownloadPackage(string packageName, string version, string destination, string queryUrl, NuGetRequest request) 
        {
            try {
                request.Verbose(string.Format(CultureInfo.InvariantCulture, "DownloadPackage' - name='{0}', version='{1}',destination='{2}', uri='{3}'", packageName, version, destination, queryUrl));

                if (new Uri(queryUrl).IsFile) {
                    throw new ArgumentException(Constants.Messages.UriSchemeNotSupported, queryUrl);
                }

                long result = 0;

                // Do not need to validate here again because the job is done by the httprepository that supplies the queryurl
                //Downloading the package
                //request.Verbose(httpquery);
                result = DownloadDataToFileAsync(destination, queryUrl, request).Result;                   

                if (result == 0 || !File.Exists(destination))
                {
                    request.Verbose(Messages.FailedDownloadPackage, packageName, queryUrl);
                    request.Warning(Constants.Messages.SourceLocationNotValid, queryUrl);
                } else {
                    request.Verbose(Messages.CompletedDownload, packageName);
                }
            } catch (Exception ex) {
                ex.Dump(request);
                request.Warning(Constants.Messages.PackageFailedInstallOrDownload, packageName, CultureInfo.CurrentCulture.TextInfo.ToLower(Constants.Download));
                throw;
            }
        }
Example #9
0
        /// <summary>
        /// Send an initial request to download data from the server.
        /// From the initial request, we may change the host of subsequent calls (if a redirection happens in this initial request)
        /// Also, if the initial request sends us less data than the amount we request, then we do not
        /// need to issue more requests
        /// </summary>
        /// <param name="query"></param>
        /// <param name="startPoint"></param>
        /// <param name="bufferSize"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        internal static Stream InitialDownloadDataToStream(UriBuilder query, int startPoint, int bufferSize, NuGetRequest request)
        {
            var uri = String.Format(CultureInfo.CurrentCulture, query.Uri.ToString(), startPoint, bufferSize);
            request.Debug(Messages.DownloadingPackage, uri);

            var client = request.Client;

            var response = PathUtility.GetHttpResponse(client, uri, (() => request.IsCanceled),
               ((msg, num) => request.Verbose(Resources.Messages.RetryingDownload, msg, num)), (msg) => request.Verbose(msg), (msg) => request.Debug(msg));


            // Check that response was successful or write error
            if (response == null || !response.IsSuccessStatusCode)
            {
                request.Warning(Resources.Messages.CouldNotGetResponseFromQuery, uri);
                return null;
            }

            // Read response and write out a stream
            var stream = GetStreamBasedOnEncoding(response);

            request.Debug(Messages.CompletedDownload, uri);

            // If the host from the response is different, change the host of the original query
            if (!String.Equals(response.RequestMessage.RequestUri.Host, query.Host, StringComparison.OrdinalIgnoreCase))
            {
                query.Host = response.RequestMessage.RequestUri.Host;
            }

            return stream;
        }
Example #10
0
        /// <summary>
        /// Download data from remote via uri query.
        /// </summary>
        /// <param name="query">Uri query</param>
        /// <param name="request">An object passed in from the PackageManagement platform that contains APIs that can be used to interact with it </param>
        /// <returns></returns>
        internal static Stream DownloadDataToStream(string query, NuGetRequest request)
        {
            request.Debug(Messages.DownloadingPackage, query);

            var client = request.Client;

            var response = PathUtility.GetHttpResponse(client, query, (()=>request.IsCanceled),
                ((msg, num) => request.Verbose(Resources.Messages.RetryingDownload, msg, num)), (msg)=>request.Verbose(msg), (msg)=>request.Debug(msg));

            // Check that response was successful or throw exception
            if (response == null || !response.IsSuccessStatusCode)
            {
                request.Warning(Resources.Messages.CouldNotGetResponseFromQuery, query);
                return null;
            }

            // Read response and write out a stream
            var stream = GetStreamBasedOnEncoding(response);

            request.Debug(Messages.CompletedDownload, query);

            return stream;
        }