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); } } }
/// <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> /// 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); }
public bool SearchPackages(string name, string requiredVersion, string minimumVersion, string maximumVersion, bool minInclusive, bool maxInclusive, int id, NuGetRequest request) { try { // If there are any packages, yield and return if (request.YieldPackages(request.GetPackageById(name, request, requiredVersion, minimumVersion, maximumVersion, minInclusive, maxInclusive), name)) { return(true); } // 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(false); } // 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(false); } // Have we been cancelled? if (request.IsCanceled) { request.Debug(Resources.Messages.RequestCanceled, PackageProviderName, "FindPackage"); return(false); } // 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. if (request.YieldPackages(request.SearchForPackages(name), name)) { return(true); } } catch (Exception ex) { ex.Dump(request); } return(false); }
/// <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> /// 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); } }
/// <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); } } }
private bool DownloadSinglePackage(PackageItem pkgItem, NuGetRequest request, string destLocation, ProgressTracker progressTracker) { try { request.Debug(Messages.DebugInfoCallMethod, "NuGetFilesFeed3", "DownloadSinglePackage"); if (string.IsNullOrWhiteSpace(pkgItem.PackageFilename) || pkgItem.PackageSource == null || pkgItem.PackageSource.Location == null || (pkgItem.PackageSource.IsSourceAFile && pkgItem.Package == null)) { request.WriteError(ErrorCategory.ObjectNotFound, pkgItem.Id, Constants.Messages.UnableToResolvePackage, pkgItem.Id); return(false); } // this is if the user says -force bool force = request.GetOptionValue("Force") != null; // combine the path and the file name destLocation = Path.Combine(destLocation, pkgItem.PackageFilename); // if the file already exists if (File.Exists(destLocation)) { // if no force, just return if (!force) { request.Verbose(Constants.Messages.SkippedDownloadedPackage, pkgItem.Id); request.YieldPackage(pkgItem, pkgItem.PackageSource.Name); return(true); } // here we know it is forced, so delete FileUtility.DeleteFile(destLocation, isThrow: false); // if after we try delete, it is still there, tells the user we can't perform the action if (File.Exists(destLocation)) { request.WriteError(ErrorCategory.ResourceUnavailable, destLocation, Constants.Messages.UnableToOverwriteExistingFile, destLocation); return(false); } } bool downloadSuccessful = false; try { // if no repository, we can't do anything if (pkgItem.PackageSource.Repository == null) { return(false); } if (pkgItem.PackageSource.Repository.IsFile) { using (var input = File.OpenRead(pkgItem.Package.FullFilePath)) { using (var output = new FileStream(destLocation, FileMode.Create, FileAccess.Write, FileShare.Read)) { input.CopyTo(output); downloadSuccessful = true; } } } else { string httpquery = MakeDownloadUri(pkgItem); if (!String.IsNullOrEmpty(httpquery)) { downloadSuccessful = NuGetClient.DownloadPackage(pkgItem.Id, pkgItem.Version, destLocation, httpquery, request, pkgItem.PackageSource, progressTracker); } else { downloadSuccessful = false; request.Warning(Messages.FailedToCreateDownloadUri, pkgItem.Id, pkgItem.Version); } } } catch (Exception ex) { ex.Dump(request); return(false); } if (downloadSuccessful) { request.Verbose(Resources.Messages.SuccessfullyDownloaded, pkgItem.Id); // provide the directory we save to to yieldpackage request.YieldPackage(pkgItem, pkgItem.PackageSource.Name, Path.GetDirectoryName(destLocation)); } return(downloadSuccessful); } finally { request.Debug(Messages.DebugInfoReturnCall, "NuGetFilesFeed3", "DownloadSinglePackage"); } }