/// <summary> /// This is called when the user is adding (or updating) a package source /// If this PROVIDER doesn't support user-defined package sources, remove this method. /// </summary> /// <param name="name"> /// The name of the package source. If this parameter is null or empty the PROVIDER should use the /// location as the name (if the PROVIDER actually stores names of package sources) /// </param> /// <param name="location"> /// The location (ie, directory, URL, etc) of the package source. If this is null or empty, the /// PROVIDER should use the name as the location (if valid) /// </param> /// <param name="trusted"> /// A boolean indicating that the user trusts this package source. Packages returned from this source /// should be marked as 'trusted' /// </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 AddPackageSource(string name, string location, bool trusted, NuGetRequest request) { // Nice-to-have put a debug message in that tells what's going on. request.Debug("Calling '{0}::AddPackageSource' '{1}','{2}','{3}'", PackageProviderName, name, location, trusted); // if they didn't pass in a name, use the location as a name. (if you support that kind of thing) name = string.IsNullOrEmpty(name) ? location : name; // let's make sure that they've given us everything we need. if (string.IsNullOrEmpty(name)) { request.Error(ErrorCategory.InvalidArgument, Constants.Parameters.Name, Constants.Messages.MissingRequiredParameter, Constants.Parameters.Name); // we're done here. return; } if (string.IsNullOrEmpty(location)) { request.Error(ErrorCategory.InvalidArgument, Constants.Parameters.Location, Constants.Messages.MissingRequiredParameter, Constants.Parameters.Location); // we're done here. return; } // if this is supposed to be an update, there will be a dynamic parameter set for IsUpdatePackageSource var isUpdate = request.GetOptionValue(Constants.Parameters.IsUpdate).IsTrue(); // if your source supports credentials you get get them too: // string username =request.Username; // SecureString password = request.Password; // feel free to send back an error here if your provider requires credentials for package sources. // check first that we're not clobbering an existing source, unless this is an update var src = request.FindRegisteredSource(name); if (src != null && !isUpdate) { // tell the user that there's one here already request.Error(ErrorCategory.InvalidArgument, name ?? location, Constants.Messages.PackageSourceExists, name ?? location); // we're done here. return; } // conversely, if it didn't find one, and it is an update, that's bad too: if (src == null && isUpdate) { // you can't find that package source? Tell that to the user request.Error(ErrorCategory.ObjectNotFound, name ?? location, Constants.Messages.UnableToResolveSource, name ?? location); // we're done here. return; } // ok, we know that we're ok to save this source // next we check if the location is valid (if we support that kind of thing) var validated = false; if (!request.SkipValidate) { // the user has not opted to skip validating the package source location, so check that it's valid (talk to the url, or check if it's a valid directory, etc) // todo: insert code to check if the source is valid validated = request.ValidateSourceLocation(location); if (!validated) { request.Error(ErrorCategory.InvalidData, name ?? location, Constants.Messages.SourceLocationNotValid, location); // we're done here. return; } // we passed validation! } // it's good to check just before you actaully write something to see if the user has cancelled the operation if (request.IsCanceled) { return; } // looking good -- store the package source // todo: create the package source (and store it whereever you store it) request.Verbose("Storing package source {0}", name); // actually yielded by the implementation. request.AddPackageSource(name, location, trusted, validated); // and, before you go, Yield the package source back to the caller. if (!request.YieldPackageSource(name, location, trusted, true /*since we just registered it*/, validated)) { // always check the return value of a yield, since if it returns false, you don't keep returning data // this can happen if they have cancelled the operation. return; } // all done! }
/// <summary> /// </summary> /// <param name="fastPackageReference"></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 InstallPackage(string fastPackageReference, NuGetRequest request) { // Nice-to-have put a debug message in that tells what's going on. request.Debug("Calling '{0}::InstallPackage' '{1}'", PackageProviderName, fastPackageReference); var pkgRef = request.GetPackageByFastpath(fastPackageReference); if (pkgRef == null) { request.Error(ErrorCategory.InvalidArgument, fastPackageReference, Constants.Messages.UnableToResolvePackage); return; } // need to make sure that the original package's sources list is tried first. request.OriginalSources = pkgRef.Sources; var dependencies = request.GetUninstalledPackageDependencies(pkgRef).Reverse().ToArray(); int progressId = 0; if (dependencies.Length > 0) { progressId = request.StartProgress(0, "Installing package '{0}'", pkgRef.GetCanonicalId(request)); } var n = 0; foreach (var d in dependencies) { request.Progress(progressId, (n*100/(dependencies.Length + 1)) + 1, "Installing dependent package '{0}'", d.GetCanonicalId(request)); if (!request.InstallSinglePackage(d)) { request.Error(ErrorCategory.InvalidResult, pkgRef.GetCanonicalId(request), Constants.Messages.DependentPackageFailedInstall, d.GetCanonicalId(request)); return; } n++; request.Progress(progressId, (n*100/(dependencies.Length + 1)), "Installed dependent package '{0}'", d.GetCanonicalId(request)); } // got this far, let's install the package we came here for. if (!request.InstallSinglePackage(pkgRef)) { // package itself didn't install. // roll that back out everything we did install. // and get out of here. request.Error(ErrorCategory.InvalidResult, pkgRef.GetCanonicalId(request), Constants.Messages.PackageFailedInstall, pkgRef.GetCanonicalId(request)); request.CompleteProgress(progressId, false); } request.CompleteProgress(progressId, true); }
/// <summary> /// </summary> /// <param name="name"></param> /// <param name="requiredVersion"></param> /// <param name="minimumVersion"></param> /// <param name="maximumVersion"></param> /// <param name="id"></param> /// <param name="request"></param> /// <returns></returns> public void FindPackage(string name, string requiredVersion, string minimumVersion, string maximumVersion, int id, NuGetRequest request) { // Nice-to-have put a debug message in that tells what's going on. request.Debug("Calling '{0}::FindPackage' '{1}','{2}','{3}','{4}','{5}'", PackageProviderName, name, requiredVersion, minimumVersion, maximumVersion, id); requiredVersion = requiredVersion.FixVersion(); if (!string.IsNullOrEmpty(requiredVersion)) { if (request.FindByCanonicalId && requiredVersion.IndexOfAny("()[],".ToCharArray()) == -1) { // when resolving packages via a canonical id, treat a lone version (ie 1.0 -> 1.0 <= x) string as a nuget version range: minimumVersion = requiredVersion; maximumVersion = null; requiredVersion = null; } else { minimumVersion = null; maximumVersion = null; } } else { minimumVersion = minimumVersion.FixVersion(); maximumVersion = maximumVersion.FixVersion(); } if (!IsValidVersionRange(minimumVersion, maximumVersion)) { request.Error(ErrorCategory.InvalidArgument, minimumVersion + maximumVersion, Constants.Messages.InvalidVersionRange, minimumVersion, maximumVersion); return; } // get the package by ID first. // if there are any packages, yield and return if (!string.IsNullOrWhiteSpace(name)) { if (request.YieldPackages(request.GetPackageById(name, requiredVersion, minimumVersion, maximumVersion), name) || request.FoundPackageById) { // if we actaully found some by that id, but didn't make it past the filter, we're done. return; } } // have we been cancelled? if (request.IsCanceled) { return; } // Try searching for matches and returning those. request.YieldPackages(request.SearchForPackages(name, requiredVersion, minimumVersion, maximumVersion), name); request.Debug("Finished '{0}::FindPackage' '{1}','{2}','{3}','{4}','{5}'", PackageProviderName, name, requiredVersion, minimumVersion, maximumVersion, id); }
/// <summary> /// Returns the packages that are installed /// </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 CORE that contains functions that can be used to interact with /// the CORE and HOST /// </param> public void GetInstalledPackages(string name, string requiredVersion, string minimumVersion, string maximumVersion, NuGetRequest request) { // Nice-to-have put a debug message in that tells what's going on. request.Debug("Calling '{0}::GetInstalledPackages' '{1}','{2}','{3}','{4}'", PackageProviderName, name, requiredVersion, minimumVersion, maximumVersion); if (requiredVersion != null) { minimumVersion = null; maximumVersion = null; } else { minimumVersion = minimumVersion.FixVersion(); maximumVersion = maximumVersion.FixVersion(); } if (!IsValidVersionRange(minimumVersion, maximumVersion)) { request.Error(ErrorCategory.InvalidArgument, minimumVersion + maximumVersion, Constants.Messages.InvalidVersionRange, minimumVersion, maximumVersion); return; } // look in the destination directory for directories that contain nupkg files. var subdirs = Directory.EnumerateDirectories(request.Destination); foreach (var subdir in subdirs) { var nupkgs = Directory.EnumerateFileSystemEntries(subdir, "*.nupkg", SearchOption.TopDirectoryOnly); foreach (var pkgFile in nupkgs) { var pkgItem = request.GetPackageByFilePath(pkgFile); if (pkgItem != null && pkgItem.IsInstalled) { if (pkgItem.Id.Equals(name, StringComparison.CurrentCultureIgnoreCase)) { if (!string.IsNullOrWhiteSpace(requiredVersion)) { if (pkgItem.Package.Version != new SemanticVersion(requiredVersion)) { continue; } } else { if (!string.IsNullOrWhiteSpace(minimumVersion) && pkgItem.Package.Version < new SemanticVersion(minimumVersion)) { continue; } if (!string.IsNullOrWhiteSpace(maximumVersion) && pkgItem.Package.Version < new SemanticVersion(maximumVersion)) { continue; } } request.YieldPackage(pkgItem, name); break; } if (string.IsNullOrEmpty(name) || pkgItem.Id.IndexOf(name, StringComparison.CurrentCultureIgnoreCase) > -1) { if (!request.YieldPackage(pkgItem, name)) { return; } } } } } }
/// <summary> /// Downloads a remote package file to a local location. /// </summary> /// <param name="fastPackageReference"></param> /// <param name="location"></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> /// <returns></returns> public void DownloadPackage(string fastPackageReference, string location, NuGetRequest request) { // Nice-to-have put a debug message in that tells what's going on. request.Debug("Calling '{0}::DownloadPackage' '{1}','{2}'", PackageProviderName, fastPackageReference, location); var pkgRef = request.GetPackageByFastpath(fastPackageReference); if (pkgRef == null) { request.Error(ErrorCategory.InvalidArgument, fastPackageReference, Constants.Messages.UnableToResolvePackage); return; } // cheap and easy copy to location. using (var input = pkgRef.Package.GetStream()) { using (var output = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.Read)) { input.CopyTo(output); } } }