/// <summary>
        /// Search the entire repository for the packages
        /// </summary>
        /// <param name="source">Package Source</param>
        /// <param name="name">Package name</param>
        /// <returns></returns>
        private IEnumerable<PackageItem> SearchForPackages(PackageSource source, string name)
        {
            try
            {
                Debug(Resources.Messages.DebugInfoCallMethod3, "NuGetRequest", "SearchForPackages", name);

                // no repository found then returns nothing
                if (source.Repository == null)
                {
                    return Enumerable.Empty<PackageItem>();
                }

                var isNameContainsWildCard = false;
                var searchTerm = Contains.Value ?? string.Empty;

                // Deal with two cases here:
                // 1. The package name contains wildcards like "Find-Package -name JQ*". We search based on the name.
                // 2. A user does not provide the Name parameter,

                // A user provides name with wildcards. We will use name as the SearchTerm while Contains and Tag will be used
                // for filtering on the results.
                if (!String.IsNullOrWhiteSpace(name) && WildcardPattern.ContainsWildcardCharacters(name))
                {
                    isNameContainsWildCard = true;

                    // NuGet does not support PowerShell/POSIX style wildcards and supports only '*' in searchTerm
                    // Replace the range from '[' - to ']' with * and ? with * then wildcard pattern is applied on the results
                    var tempName = name;
                    var squareBracketPattern = Regex.Escape("[") + "(.*?)]";
                    foreach (Match match in Regex.Matches(tempName, squareBracketPattern)) {
                        tempName = tempName.Replace(match.Value, "*");
                    }

                    //As the nuget does not support wildcard, we remove '?', '*' wildcards from the search string, and then
                    //looking for the longest string in the given string as a keyword for the searching in the repository.
                    //A sample case will be something like find-package sql*Compact*.

                    //When the AllVersions property exists, the query like the following containing the wildcards does not work. We need to remove the wild cards and
                    //replace it with the longest string searhc.
                    //http://www.powershellgallery.com/api/v2/Search()?$orderby=DownloadCount%20desc,Id&searchTerm='tsdprovi*'&targetFramework=''&includePrerelease=false

                    if ((!String.IsNullOrWhiteSpace(name) && source.Location.IndexOf("powershellgallery.com", StringComparison.OrdinalIgnoreCase) == -1)
                        || (AllVersions.Value))
                    {
                        //get rid of wildcard and search the longest string in the given name for nuget.org
                        tempName = tempName.Split('?', '*').OrderBy(namePart => namePart.Length).Last();
                    }

                    //Deal with a case when a user type Find-Package *
                    if (String.Equals(tempName, "*", StringComparison.OrdinalIgnoreCase)) {
                        //We use '' instead of "*" because searchterm='*' does not return the entire repository.
                        tempName = string.Empty;
                    }

                    searchTerm = tempName;
                }

                // Add the Tags for the search.
                if (FilterOnTag != null)
                {
                    // E.g. searchTerm = "tag:dscresource_xFirefox tag:command_Start-Process"
                    searchTerm = FilterOnTag.Value.Where(tag => !string.IsNullOrWhiteSpace(tag)).Aggregate(searchTerm, (current, tag) => current + " tag:" + tag);
                }

                Verbose(Resources.Messages.SearchingRepository, source.Repository.Source, searchTerm);

                // Handling case where a user does not provide Name parameter
                var pkgs = source.Repository.Search(searchTerm, this);

                if (!String.IsNullOrWhiteSpace(name))
                {
                    //Filter on the results. This is needed because we replace [...] regex in the searchterm at the begining of this method.
                    pkgs = FilterOnName(pkgs, name, isNameContainsWildCard);
                }

                pkgs = FilterOnContains(pkgs);

                var pkgsItem = pkgs.Select(pkg => new PackageItem
                   {
                       Package = pkg,
                       PackageSource = source,
                       FastPath = MakeFastPath(source, pkg.Id, pkg.Version.ToString())
                   });

                return pkgsItem;
            }
            catch (Exception e)
            {
                e.Dump(this);
                Warning(e.Message);
                return Enumerable.Empty<PackageItem>();
            }
        }
        private IEnumerable<PackageItem> GetPackageById(PackageSource source, 
            string name,
            NuGetRequest request, 
            string requiredVersion = null, 
            string minimumVersion = null, 
            string maximumVersion = null,
            bool minInclusive = true,
            bool maxInclusive = true)
        {
            try {
                Debug(Resources.Messages.DebugInfoCallMethod3, "NuGetRequest", "GetPackageById", name);

                // source should be attached to a repository
                if (source.Repository == null)
                {
                    return Enumerable.Empty<PackageItem>();
                }

                // otherwise fall back to traditional behavior
                var pkgs = source.Repository.FindPackagesById(name, request);

                // exact version is required if required version is not null or empty OR maxversion == minversion and min and max inclusive are true
                bool exactVersionRequired = (!string.IsNullOrWhiteSpace(requiredVersion))
                    || (!string.IsNullOrWhiteSpace(maximumVersion)
                        && !string.IsNullOrWhiteSpace(minimumVersion)
                        && (new SemanticVersion(minimumVersion) == new SemanticVersion(maximumVersion))
                        && minInclusive && maxInclusive);

                // if required version not specified then don't use unlisted version
                // unlisted version is the one that has published year as 1900
                if (!exactVersionRequired)
                {
                    pkgs = pkgs.Where(pkg => pkg.Published.HasValue && pkg.Published.Value.Year > 1900);
                }

                if (AllVersions.Value){
                    //Display versions from lastest to oldest
                    pkgs = (from p in pkgs select p).OrderByDescending(x => x.Version);
                }
                else if (String.IsNullOrWhiteSpace(requiredVersion) && String.IsNullOrWhiteSpace(minimumVersion) && String.IsNullOrWhiteSpace(maximumVersion))
                {

                    if (AllowPrereleaseVersions.Value || source.Repository.IsFile) {
                        //Handling something like Json.NET 7.0.1-beta3 as well as local repository
                        pkgs = from p in pkgs
                            group p by p.Id
                            into newGroup
                                   select newGroup.Aggregate((current, next) => (next.Version > current.Version) ? next : current);

                    } else {
                        pkgs = from p in pkgs where p.IsLatestVersion select p;
                    }
                }
                else if (!exactVersionRequired && !AllowPrereleaseVersions.Value)
                {
                    // if exact version is not required and allow prerelease is false, we will have to filter out prerelease version
                    pkgs = from p in pkgs where string.IsNullOrWhiteSpace(p.Version.SpecialVersion) select p;
                }

                pkgs = FilterOnContains(pkgs);
                pkgs = FilterOnTags(pkgs);

                var results = FilterOnVersion(pkgs, requiredVersion, minimumVersion, maximumVersion, minInclusive, maxInclusive)
                    .Select(pkg => new PackageItem {
                        Package = pkg,
                        PackageSource = source,
                        FastPath = MakeFastPath(source, pkg.Id, pkg.Version.ToString())
                    });
                return results;
            } catch (Exception e) {
                e.Dump(this);
                return Enumerable.Empty<PackageItem>();
            }
        }
        private PackageSource ResolvePackageSource(string nameOrLocation)
        {
            Debug(Resources.Messages.DebugInfoCallMethod3, "NuGetRequest", "ResolvePackageSource", nameOrLocation);

            if (IsCanceled) {
                return null;
            }

            var source = FindRegisteredSource(nameOrLocation);
            if (source != null) {
                Debug(Resources.Messages.FoundRegisteredSource, nameOrLocation, NuGetConstant.ProviderName);
                return source;
            }

            Debug(Resources.Messages.NotFoundRegisteredSource, nameOrLocation, NuGetConstant.ProviderName);

            try {
                // is the given value a filename?
                if (File.Exists(nameOrLocation)) {
                    Debug(Resources.Messages.SourceIsAFilePath, nameOrLocation);

                    return new PackageSource() {
                        Request = this,
                        IsRegistered = false,
                        IsValidated = true,
                        Location = nameOrLocation,
                        Name = nameOrLocation,
                        Trusted = true,
                    };
                }
            } catch {
            }

            try {
                // is the given value a directory?
                if (Directory.Exists(nameOrLocation)) {
                    Debug(Resources.Messages.SourceIsADirectory, nameOrLocation);
                    return new PackageSource() {
                        Request = this,
                        IsRegistered = false,
                        IsValidated = true,
                        Location = nameOrLocation,
                        Name = nameOrLocation,
                        Trusted = true,
                    };
                }
            } catch {
            }

            if (Uri.IsWellFormedUriString(nameOrLocation, UriKind.Absolute)) {
                var uri = new Uri(nameOrLocation, UriKind.Absolute);
                if (!SupportedSchemes.Contains(uri.Scheme.ToLowerInvariant())) {
                    WriteError(ErrorCategory.InvalidArgument, uri.ToString(), Constants.Messages.UriSchemeNotSupported, uri);
                    return null;
                }

                // this is an URI, and it looks like one type that we support
                if (SkipValidate.Value || NuGetPathUtility.ValidateSourceUri(SupportedSchemes, uri, this)) {
                    var uriSource = new PackageSource {
                        Request = this,
                        IsRegistered = false,
                        IsValidated = !SkipValidate.Value,
                        Location = nameOrLocation,
                        Name = nameOrLocation,
                        Trusted = false,
                    };

                    return uriSource;
                }
            }

            WriteError(ErrorCategory.InvalidArgument, nameOrLocation, Constants.Messages.UnableToResolveSource, nameOrLocation);
            return null;
        }
        /// <summary>
        /// Encrypting a path containing package source location, id, version and source
        /// </summary>
        /// <param name="source">package source</param>
        /// <param name="id">package id</param>
        /// <param name="version">package version</param>
        /// <returns></returns>
        internal string MakeFastPath(PackageSource source, string id, string version)
        {
            // if this is called from powershellget, append nonupkg at the end
            if (IsCalledFromPowerShellGet)
            {
                return String.Format(CultureInfo.InvariantCulture, @"${0}\{1}\{2}\{3}\{4}", source.Serialized, id.ToBase64(), version.ToBase64(), (Sources ?? new string[0]).Select(each => each.ToBase64()).SafeAggregate((current, each) => current + "|" + each), "powershellget".ToBase64());
            }

            return String.Format(CultureInfo.InvariantCulture, @"${0}\{1}\{2}\{3}", source.Serialized, id.ToBase64(), version.ToBase64(), (Sources ?? new string[0]).Select(each => each.ToBase64()).SafeAggregate((current, each) => current + "|" + each));
        }
Beispiel #5
0
 /// <summary>
 /// Encrypting a path containing package source location, id, version and source
 /// </summary>
 /// <param name="source">package source</param>
 /// <param name="id">package id</param>
 /// <param name="version">package version</param>
 /// <returns></returns>
 internal string MakeFastPath(PackageSource source, string id, string version) {
     return String.Format(CultureInfo.InvariantCulture, @"${0}\{1}\{2}\{3}", source.Serialized, id.ToBase64(), version.ToBase64(), (Sources ?? new string[0]).Select(each => each.ToBase64()).SafeAggregate((current, each) => current + "|" + each));
 }
        /// <summary>
        /// Download a package from a file repository that matches the given version and name and install it on the local system.
        /// </summary>
        /// <param name="packageName">Package name</param>
        /// <param name="version">Package version</param>
        /// <param name="request">An object passed in from the PackageManagement platform that contains APIs that can be used to interact with it </param>  
        /// <param name="source">Package source</param>
        /// <param name="sourceFilePath">File source path pointing to the package to be installed</param>
        /// <returns>PackageItem object</returns>
        internal static PackageItem InstallPackageLocal(
            string packageName, 
            string version,
            NuGetRequest request, 
            PackageSource source,             
            string sourceFilePath 
            )
        {
            request.Debug(Messages.DebugInfoCallMethod, "NuGetClient", "InstallPackageLocal");

            string tempSourceFilePath = null;
            string tempSourceDirectory = null;

            string directoryToDeleteWhenFailed = String.Empty;
            bool needToDelete = false;

            try 
            {
                string destinationFilePath = request.Destination;
                request.Verbose(string.Format(CultureInfo.InvariantCulture, "InstallPackageLocal' - name='{0}', version='{1}',destination='{2}'", packageName, version, destinationFilePath));
                request.Debug(sourceFilePath);

                if (string.IsNullOrWhiteSpace(sourceFilePath))
                {
                    throw new ArgumentNullException(sourceFilePath);
                }

                if (!File.Exists(sourceFilePath)) {
                    throw new FileNotFoundException(sourceFilePath);
                }

                //Create the destination directory if it does not exist
                if (!Directory.Exists(destinationFilePath)) {
                    Directory.CreateDirectory(destinationFilePath);
                    directoryToDeleteWhenFailed = destinationFilePath;
                }

                //Make a temp folder in the user appdata temp directory 
                tempSourceFilePath = FileUtility.GetTempFileFullPath(fileExtension: NuGetConstant.PackageExtension);

                //Copy over the source file from  the folder repository to the temp folder
                File.Copy(sourceFilePath, tempSourceFilePath, true);

                //Unzip it
                tempSourceDirectory = PackageUtility.DecompressFile(tempSourceFilePath);

                //Get a packge directory under the destination path to store the package
                string installedFolder = FileUtility.MakePackageDirectoryName(request.ExcludeVersion.Value, destinationFilePath, packageName, version);

                // if we did not set the directory before, then the destinationFilePath already exists, so we should not delete it
                if (string.IsNullOrWhiteSpace(directoryToDeleteWhenFailed))
                {
                    directoryToDeleteWhenFailed = installedFolder;
                }

                //File folder format of the Nuget packages looks like the following after installed:
                //Jquery.2.0.1
                //  - JQuery.2.0.1.nupkg
                //  - contents and other stuff

                //Copy the unzipped files to under the package installed folder
                FileUtility.CopyDirectory(tempSourceDirectory, installedFolder, true);

                 //Read the package manifest and return the package object
                string nuspec = Path.Combine(installedFolder, packageName) + NuGetConstant.ManifestExtension;

                PackageBase package = PackageUtility.ProcessNuspec(nuspec);

                var pkgItem = new PackageItem {
                    Package = package,
                    PackageSource = source,
                    FastPath = request.MakeFastPath(source, package.Id, package.Version),
                    FullPath = installedFolder
                };

                // Delete the nuspec file
                //Get a package file path
                var nuspecFilePath = Path.Combine(installedFolder, packageName + NuGetConstant.ManifestExtension);

                if (File.Exists(nuspecFilePath))
                {
                    FileUtility.DeleteFile(nuspecFilePath, false);
                }

                request.Debug(Messages.DebugInfoReturnCall, "NuGetClient", "InstallPackageLocal");

                return pkgItem;

            } catch (Exception ex) {
                needToDelete = true;
                // the warning will be package "packageName" failed to install
                ex.Dump(request);
                request.WriteError(ErrorCategory.InvalidResult, packageName, Constants.Messages.PackageFailedInstallOrDownload, packageName, CultureInfo.CurrentCulture.TextInfo.ToLower(Constants.Install));
                throw;
            } finally {
                if (needToDelete && Directory.Exists(directoryToDeleteWhenFailed))
                {
                    FileUtility.DeleteDirectory(directoryToDeleteWhenFailed, true, isThrow: false);
                }

                FileUtility.DeleteFile(tempSourceFilePath, isThrow:false);
                FileUtility.DeleteDirectory(tempSourceDirectory, recursive: true, isThrow: false);
            }
        }
        /// <summary>
        /// Download a package that matches the given version and name and install it on the local system.
        /// </summary>
        /// <param name="packageName">Package name</param>
        /// <param name="version">Package version</param>
        /// <param name="request">An object passed in from the PackageManagement platform that contains APIs that can be used to interact with it </param>  
        /// <param name="source">Package source</param>
        /// <param name="queryUrl">Full uri</param>
        /// <param name="packageHash">the hash of the package</param>
        /// <param name="packageHashAlgorithm">the hash algorithm of the package</param>
        /// <returns>PackageItem object</returns>
        internal static PackageItem InstallPackage(
            string packageName,
            string version,
            NuGetRequest request,
            PackageSource source,
            string queryUrl,
            string packageHash,
            string packageHashAlgorithm
            ) 
        {
            request.Debug(Messages.DebugInfoCallMethod, "NuGetClient", "InstallPackage");

            //If the destination folder does not exists, create it
            string destinationPath = request.Destination;
            request.Verbose(string.Format(CultureInfo.InvariantCulture, "InstallPackage' - name='{0}', version='{1}',destination='{2}'", packageName, version, destinationPath));

            string directoryToDeleteWhenFailed = string.Empty;
            bool needToDelete = false;
            string installFullPath = string.Empty;

            try
            {
                if (!Directory.Exists(destinationPath)) {
                    Directory.CreateDirectory(destinationPath);
                    // delete the destinationPath later on if we fail to install and if destinationPath did not exist before
                    directoryToDeleteWhenFailed = destinationPath;
                }

                //Create a folder under the destination path to hold the package
                string installDir = FileUtility.MakePackageDirectoryName(request.ExcludeVersion.Value, destinationPath, packageName, version);

                if (!Directory.Exists(installDir)) {
                    Directory.CreateDirectory(installDir);

                    // if directoryToDeleteWhenFailed is null then the destinationPath already exists before so we should not delete it
                    if (String.IsNullOrWhiteSpace(directoryToDeleteWhenFailed))
                    {
                        directoryToDeleteWhenFailed = installDir;
                    }
                }

                //Get the package file name based on the version and id
                string fileName = FileUtility.MakePackageFileName(request.ExcludeVersion.Value, packageName, version);

                installFullPath = Path.Combine(installDir, fileName);

                //download to fetch the package
                DownloadPackage(packageName, version, installFullPath, queryUrl, request);

                // check that we have the file
                if (!File.Exists(installFullPath))
                {
                    needToDelete = true;
                    request.WriteError(ErrorCategory.ResourceUnavailable, installFullPath, Constants.Messages.PackageFailedInstallOrDownload, packageName,
                        CultureInfo.CurrentCulture.TextInfo.ToLower(Constants.Install));
                    return null;
                }

                #region verify hash
                //we don't enable checking for hash here because it seems like nuget provider does not
                //checks that there is hash. Otherwise we don't carry out the install
                
                if (string.IsNullOrWhiteSpace(packageHash) || string.IsNullOrWhiteSpace(packageHashAlgorithm))
                {
                    // delete the file downloaded. VIRUS!!!
                    needToDelete = true;
                    request.WriteError(ErrorCategory.SecurityError, packageName, Constants.Messages.HashNotFound, packageName);
                    return null;
                }

                // Verify the hash
                using (FileStream stream = File.OpenRead(installFullPath))
                {
                    HashAlgorithm hashAlgorithm = null;

                    switch (packageHashAlgorithm.ToLowerInvariant())
                    {
                        case "sha256":
                            hashAlgorithm = SHA256.Create();
                            break;

                        case "md5":
                            hashAlgorithm = MD5.Create();
                            break;

                        case "sha512":
                        // Flows to default case

                        // default to sha512 algorithm
                        default:
                            hashAlgorithm = SHA512.Create();
                            break;
                    }

                    if (hashAlgorithm == null)
                    {
                        // delete the file downloaded. VIRUS!!!
                        needToDelete = true;
                        request.WriteError(ErrorCategory.SecurityError, packageHashAlgorithm, Constants.Messages.HashNotSupported, packageHashAlgorithm);
                        return null;
                    }

                    // compute the hash
                    byte[] computedHash = hashAlgorithm.ComputeHash(stream);

                    // convert the original hash we got from the feed
                    byte[] downloadedHash = Convert.FromBase64String(packageHash);

                    // if they are not equal, just issue out verbose because there is a current bug in backend
                    // where editing the published module will result in a package with a different hash than the one
                    // provided on the feed
                    if (!Enumerable.SequenceEqual(computedHash, downloadedHash))
                    {
                        // delete the file downloaded. VIRUS!!!
                        request.Verbose(Constants.Messages.HashNotMatch, packageName);
                    }

                    //parse the package
                    var pkgItem = InstallPackageLocal(packageName, version, request, source, installFullPath);
                    return pkgItem;
                }
                #endregion

            }
            catch (Exception e)
            {
                request.Debug(e.Message);
                needToDelete = true;
            }
            finally
            {
                if (needToDelete)
                {
                    // if the directory exists just delete it because it will contains the file as well
                    if (!String.IsNullOrWhiteSpace(directoryToDeleteWhenFailed) && Directory.Exists(directoryToDeleteWhenFailed))
                    {
                        try
                        {
                            FileUtility.DeleteDirectory(directoryToDeleteWhenFailed, true, isThrow: false);
                        }
                        catch { }
                    }

                    // if for some reason, we can't delete the directory or if we don't need to delete the directory
                    // then we have to delete installFullPath
                    if (File.Exists(installFullPath))
                    {
                        FileUtility.DeleteFile(installFullPath, isThrow: false);
                    }
                }
            }

            return null;
        }
Beispiel #8
0
        /// <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>   
        /// <param name="pkgSource">source to download the package</param>
        /// <param name="progressTracker">Utility class to help track progress</param>
        /// 
        internal static bool DownloadPackage(string packageName, string version, string destination, string queryUrl, NuGetRequest request, PackageSource pkgSource, ProgressTracker progressTracker) 
        {
            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, PathUtility.GetNetworkCredential(request.CredentialUsername, request.CredentialPassword), progressTracker).Result;                   

                if (result == 0 || !File.Exists(destination))
                {
                    request.Verbose(Messages.FailedDownloadPackage, packageName, queryUrl);
                    request.Warning(Constants.Messages.SourceLocationNotValid, queryUrl);
                    return false;
                } else {
                    request.Verbose(Messages.CompletedDownload, packageName);
                    return true;
                }
            } catch (Exception ex) {
                ex.Dump(request);
                request.Warning(Constants.Messages.PackageFailedInstallOrDownload, packageName, CultureInfo.CurrentCulture.TextInfo.ToLower(Constants.Download));
                throw;
            }
        }