Exemplo n.º 1
0
        /// <summary>
        /// Installs a given package.
        /// </summary>
        /// <param name="fastPackageReference">A provider supplied identifier that specifies an exact package</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 InstallPackage(string fastPackageReference, NuGetRequest request) 
        {
            if (request == null){
                throw new ArgumentNullException("request");
            }

            request.Debug(Resources.Messages.DebugInfoCallMethod3, PackageProviderName, "InstallPackage", fastPackageReference);

            try {

                var pkgItem = request.GetPackageByFastpath(fastPackageReference);
                if (pkgItem == null) {
                    request.WriteError(ErrorCategory.InvalidArgument, fastPackageReference, Constants.Messages.UnableToResolvePackage);
                    return;
                }

                if ((pkgItem.PackageSource == null) || (pkgItem.PackageSource.Location == null) || (pkgItem.Package == null)) {
                    request.Debug(Resources.Messages.VariableCheck, "PackageSource or PackageSource.Location or Package object", "null");
                    request.WriteError(ErrorCategory.ObjectNotFound, fastPackageReference, Constants.Messages.UnableToResolvePackage, pkgItem.Id);
                    return;
                }

                request.Debug(Resources.Messages.VariableCheck, "Package version", pkgItem.Version);
                request.Debug(Resources.Messages.VariableCheck, "Request's Destination", request.Destination);

                // got this far, let's install the package we came here for.
                if (!NuGetClient.InstallOrDownloadPackageHelper(pkgItem, request, Constants.Install,
                    (packageItem, progressTracker) => NuGetClient.InstallSinglePackage(packageItem, request, progressTracker)))
                {
                    // package itself didn't install. Write error
                    request.WriteError(ErrorCategory.InvalidResult, pkgItem.Id, Constants.Messages.PackageFailedInstallOrDownload, pkgItem.Id, CultureInfo.CurrentCulture.TextInfo.ToLower(Constants.Install));

                    return;
                }
            } catch (Exception ex) {
                ex.Dump(request);
                request.WriteError(ErrorCategory.InvalidOperation, fastPackageReference, ex.Message);
            }
        }
Exemplo n.º 2
0
        /// <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 PackageManagement that contains functions that can be used to interact with its Provider</param> 
        public void AddPackageSource(string name, string location, bool trusted, NuGetRequest request)
        {
            if (request == null){
                throw new ArgumentNullException("request");
            }
            try {
                request.Debug(string.Format(CultureInfo.InvariantCulture, "AddPackageSource - ProvidenName = '{0}', name='{1}', location='{2}', trusted='{3}'", PackageProviderName, name, location, trusted));

                // Error out if a user does not provide package source Name
                if (string.IsNullOrWhiteSpace(name))
                {
                    request.WriteError(ErrorCategory.InvalidArgument, Constants.Parameters.Name, Constants.Messages.MissingRequiredParameter, Constants.Parameters.Name);
                    return;
                }

                if (string.IsNullOrWhiteSpace(location))
                {
                    request.WriteError(ErrorCategory.InvalidArgument, Constants.Parameters.Location, Constants.Messages.MissingRequiredParameter, Constants.Parameters.Location);
                    return;
                }

                request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, "GetOptionValue");
                // 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();

                request.Debug(Resources.Messages.VariableCheck, "IsUpdate", isUpdate);

                // 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

                request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, string.Format(CultureInfo.InvariantCulture, "FindRegisteredSource -name'{0}'", name));

                var src = request.FindRegisteredSource(name);

                if (src != null && !isUpdate)
                {
                    // tell the user that there's one here already
                    request.WriteError(ErrorCategory.InvalidArgument, name, Constants.Messages.PackageSourceExists, name);
                    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.WriteError(ErrorCategory.ObjectNotFound, name, Constants.Messages.UnableToResolveSource, name);
                    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.Value)
                {
                    // the user has not opted to skip validating the package source location, so check if the source is valid
                    validated = request.ValidateSourceLocation(location);

                    if (!validated)
                    {
                        request.WriteError(ErrorCategory.InvalidData, name, Constants.Messages.SourceLocationNotValid, location);
                        return;
                    }

                    request.Verbose(Resources.Messages.SuccessfullyValidated, name);
                }

                // it's good to check just before you actually write something to see if the user has cancelled the operation
                if (request.IsCanceled)
                {
                    return;
                }

                // looking good -- store the package source.
                request.AddPackageSource(name, location, trusted, validated);

                // Yield the package source back to the caller.
                request.YieldPackageSource(name, location, trusted, true /*since we just registered it*/, validated);
            }
            catch (Exception e)
            {
                e.Dump(request);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Downloads a remote package file to a local location.
        /// </summary>
        /// <param name="fastPackageReference"></param>
        /// <param name="destLocation"></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 DownloadPackage(string fastPackageReference, string destLocation, NuGetRequest request)
        {
            if (request == null){
                throw new ArgumentNullException("request");
            }

            request.Debug(Resources.Messages.DebugInfoCallMethod3, PackageProviderName, fastPackageReference, destLocation);

            try {
                var pkgItem = request.GetPackageByFastpath(fastPackageReference);
                if (pkgItem == null) {
                    request.WriteError(ErrorCategory.InvalidArgument, fastPackageReference, Constants.Messages.UnableToResolvePackage);
                    return;
                }

                NuGetClient.InstallOrDownloadPackageHelper(pkgItem, request, Constants.Download,
                    (packageItem, progressTracker) => NuGetClient.DownloadSinglePackage(packageItem, request, destLocation, progressTracker));
            } catch (Exception ex) {
                ex.Dump(request);
                request.WriteError(ErrorCategory.InvalidOperation, fastPackageReference, ex.Message);
            }
        }
        /// <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);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Returns the validated uri. Returns null if we cannot validate it
        /// </summary>
        /// <param name="query"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        internal static Uri ValidateUri(Uri query, NuGetRequest request)
        {
            var client = request.ClientWithoutAcceptHeader;

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

            if (response == null)
            {
                return null;
            }

            // if response is not success, we need to check for redirection
            if (!response.IsSuccessStatusCode)
            {
                // Check for redirection (http status code 3xx)
                if (response.StatusCode == HttpStatusCode.MultipleChoices || response.StatusCode == HttpStatusCode.MovedPermanently
                    || response.StatusCode == HttpStatusCode.Found || response.StatusCode == HttpStatusCode.SeeOther
                    || response.StatusCode == HttpStatusCode.TemporaryRedirect)
                {
                    // get the redirected direction
                    string location = response.Headers.GetValues("Location").FirstOrDefault();
                    if (String.IsNullOrWhiteSpace(location))
                    {
                        return null;
                    }

                    // make a new query based on location
                    query = new Uri(location);
                }
                else
                {
                    if (response.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        request.WriteError(ErrorCategory.PermissionDenied, "ValidateUri", Resources.Messages.AccessPermissionDenied, query);
                    }

                    // other status code is wrong
                    return null;
                }
            }
            else
            {
                query = new Uri(response.RequestMessage.RequestUri.AbsoluteUri);
            }

            //Making a query like: www.nuget.org/api/v2/FindPackagesById()?id='FoooBarr' to check the server available.
            //'FoooBarr' is an any random package id
            string queryUri = "FoooBarr".MakeFindPackageByIdQuery(PathUtility.UriCombine(query.AbsoluteUri, NuGetConstant.FindPackagesById));

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

            // The link is not valid
            if (response == null || !response.IsSuccessStatusCode)
            {
                return null;
            }

            return query;
        }
        /// <summary>
        /// Returns the package dependencies of packageItem. We only return the dependencies that are not installed in the destination folder of request
        /// </summary>
        /// <param name="packageItem"></param>
        /// <param name="request"></param>
        private static IEnumerable<PackageItem> GetPackageDependenciesHelper(PackageItem packageItem, NuGetRequest request)
        {
            if (packageItem.Package.DependencySetList == null)
            {
                yield break;
            }

            foreach (var depSet in packageItem.Package.DependencySetList)
            {
                if (depSet.Dependencies == null)
                {
                    continue;
                }

                foreach (var dep in depSet.Dependencies)
                {
                    // Get the min dependencies version
                    string minVersion = dep.DependencyVersion.MinVersion.ToStringSafe();

                    // Get the max dependencies version
                    string maxVersion = dep.DependencyVersion.MaxVersion.ToStringSafe();

                    // check whether it is already installed at the destination
                    if (request.GetInstalledPackages(dep.Id, null, minVersion, maxVersion, minInclusive: dep.DependencyVersion.IsMinInclusive, maxInclusive: dep.DependencyVersion.IsMaxInclusive, terminateFirstFound: true))
                    {
                        request.Verbose(String.Format(CultureInfo.CurrentCulture, Messages.AlreadyInstalled, dep.Id));
                        // already have a dependency so move on
                        continue;
                    }

                    // get all the packages that match this dependency
                    var dependentPackageItem = request.GetPackageById(dep.Id, request, minimumVersion: minVersion, maximumVersion: maxVersion, minInclusive: dep.DependencyVersion.IsMinInclusive, maxInclusive: dep.DependencyVersion.IsMaxInclusive).ToArray();

                    if (dependentPackageItem.Length == 0)
                    {
                        request.WriteError(ErrorCategory.ObjectNotFound, dep.Id, Constants.Messages.UnableToFindDependencyPackage, dep.Id);

                        break;
                    }

                    // Get the package that is the latest version
                   yield return dependentPackageItem.OrderByDescending(each => each.Version).FirstOrDefault();
                }
            }
        }
        /// <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;
        }
        /// <summary>
        /// Install a single package. Also install any of its dependency if they are available (the dependency will be installed first).
        /// For dependencies, we will only get those that are not installed.
        /// Operation is either install or download
        /// installOrDownloadFunction is a function that takes in a packageitem and performs either install or download on it
        /// </summary>
        /// <param name="pkgItem"></param>
        /// <param name="request"></param>
        /// <param name="operation"></param>
        /// <param name="installOrDownloadFunction"></param>
        /// <returns></returns>
        internal static bool InstallOrDownloadPackageHelper(PackageItem pkgItem, NuGetRequest request, string operation, Func<PackageItem, bool> installOrDownloadFunction)
        {
            // pkgItem.Sources is the source that the user input. The request will try this source.
            request.OriginalSources = pkgItem.Sources;

            int progressId = 0;

            bool hasDependencyLoop = false;
            // Get the dependencies that are not already installed
            var dependencies = NuGetClient.GetPackageDependenciesToInstall(request, pkgItem, ref hasDependencyLoop).ToArray();
             
            // If there is a dependency loop. Warn the user and don't install the package
            if (hasDependencyLoop)
            {
                // package itself didn't install. Report error
                request.WriteError(ErrorCategory.DeadlockDetected, pkgItem.Id, Constants.Messages.DependencyLoopDetected, pkgItem.Id);
                return false;
            }

            // request may get canceled if there is a package dependencies missing
            if (request.IsCanceled)
            {
                return false;
            }

            int n = 0;
            int numberOfDependencies = dependencies.Count();

            // Start progress
            progressId = request.StartProgress(0, string.Format(CultureInfo.InvariantCulture, Messages.InstallingOrDownloadingPackage, operation, pkgItem.Id));

            try
            {
                // check that this package has dependency and the user didn't want to skip dependencies
                if (numberOfDependencies > 0)
                {
                    // let's install dependencies
                    foreach (var dep in dependencies)
                    {
                        request.Progress(progressId, (n * 100 / (numberOfDependencies + 1)) + 1, string.Format(CultureInfo.InvariantCulture, Messages.InstallingOrDownloadingDependencyPackage, operation, dep.Id));
                        // Check that we successfully installed the dependency
                        if (!installOrDownloadFunction(dep))
                        {
                            request.WriteError(ErrorCategory.InvalidResult, dep.Id, Constants.Messages.DependentPackageFailedInstallOrDownload, dep.Id, CultureInfo.CurrentCulture.TextInfo.ToLower(operation));
                            return false;
                        }
                        n++;
                        request.Progress(progressId, (n * 100 / (numberOfDependencies + 1)), string.Format(CultureInfo.InvariantCulture, Messages.InstalledOrDownloadedDependencyPackage, operation, dep.Id));
                    }
                }

                // Now let's install the main package
                if (installOrDownloadFunction(pkgItem))
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                ex.Dump(request);
            }
            finally
            {
                // Report that we have completed installing the package and its dependency this does not mean there are no errors.
                // Just that it's completed.
                request.CompleteProgress(progressId, false);
            }
            
            // package itself didn't install. Report error
            request.WriteError(ErrorCategory.InvalidResult, pkgItem.Id, Constants.Messages.PackageFailedInstallOrDownload, pkgItem.Id, CultureInfo.CurrentCulture.TextInfo.ToLower(operation));

            return false;
        }
        /// <summary>
        /// Download a single package to destination without checking for dependencies
        /// </summary>
        /// <param name="pkgItem"></param>
        /// <param name="request"></param>
        /// <param name="destLocation"></param>
        /// <returns></returns>
        internal static bool DownloadSinglePackage(PackageItem pkgItem, NuGetRequest request, string destLocation)
        {
            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;
                }
            }
            
            try
            {
                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);
                        }
                    }
                }
                else
                {
                    //V2 download package protocol:
                    //sample url: http://www.nuget.org/api/v2/package/jQuery/2.1.3
                    string append = String.Format(CultureInfo.InvariantCulture, "/package/{0}/{1}", pkgItem.Id, pkgItem.Version);
                    string httpquery = PathUtility.UriCombine(pkgItem.PackageSource.Repository.Source, append);

                    NuGetClient.DownloadPackage(pkgItem.Id, pkgItem.Version, destLocation,
                        string.IsNullOrWhiteSpace(pkgItem.Package.ContentSrcUrl) ? httpquery : pkgItem.Package.ContentSrcUrl, request);
                }
            }
            catch (Exception ex)
            {
                ex.Dump(request);
                return false;
            }

            request.Verbose(Resources.Messages.SuccessfullyDownloaded, pkgItem.Id);
            request.YieldPackage(pkgItem, pkgItem.PackageSource.Name);

            return true;
        }
Exemplo n.º 10
0
        /// <summary>
        /// Returns the package dependencies of packageItem. We only return the dependencies that are not installed in the destination folder of request
        /// </summary>
        /// <param name="packageItem"></param>
        /// <param name="processedDependencies"></param>
        /// <param name="request"></param>
        private static IEnumerable<PackageItem> GetPackageDependenciesHelper(PackageItem packageItem, HashSet<string> processedDependencies, NuGetRequest request)
        {
            if (packageItem.Package.DependencySetList == null)
            {
                yield break;
            }

            bool force = request.GetOptionValue("Force") != null;
            foreach (var depSet in packageItem.Package.DependencySetList)
            {
                if (depSet.Dependencies == null)
                {
                    continue;
                }

                foreach (var dep in depSet.Dependencies)
                {
                    var depKey = string.Format(CultureInfo.InvariantCulture, "{0}!#!{1}", dep.Id, dep.DependencyVersion.ToStringSafe());

                    if (processedDependencies.Contains(depKey))
                    {
                        continue;
                    }

                    // Get the min dependencies version
                    string minVersion = dep.DependencyVersion.MinVersion.ToStringSafe();

                    // Get the max dependencies version
                    string maxVersion = dep.DependencyVersion.MaxVersion.ToStringSafe();

                    if (!force)
                    {
                        bool installed = false;

                        var installedPackages = request.InstalledPackages.Value;

                        if (request.InstalledPackages.Value.Count() > 0)
                        {
                            // check the installedpackages options passed in
                            foreach (var installedPackage in request.InstalledPackages.Value)
                            {
                                // if name not match, move on to the next entry
                                if (!string.Equals(installedPackage.Id, dep.Id, StringComparison.OrdinalIgnoreCase))
                                {
                                    continue;
                                }

                                // if no version and if name matches, skip
                                if (string.IsNullOrWhiteSpace(installedPackage.Version))
                                {
                                    // skip this dependency
                                    installed = true;
                                    break;
                                }

                                SemanticVersion packageVersion = new SemanticVersion(installedPackage.Version);

                                // checks min and max
                                if (request.MinAndMaxVersionMatched(packageVersion, minVersion, maxVersion, dep.DependencyVersion.IsMinInclusive, dep.DependencyVersion.IsMaxInclusive))
                                {
                                    // skip this dependency
                                    installed = true;
                                    break;
                                }
                            }
                        }
                        // check whether package is installed at destination. only used this option if installedpackages not passed in
                        else if (request.GetInstalledPackages(dep.Id, null, minVersion, maxVersion, minInclusive: dep.DependencyVersion.IsMinInclusive, maxInclusive: dep.DependencyVersion.IsMaxInclusive, terminateFirstFound: true))
                        {
                            installed = true;
                        }

                        if (installed)
                        {
                            // already processed this so don't need to do this next time
                            processedDependencies.Add(dep.Id);
                            request.Verbose(String.Format(CultureInfo.CurrentCulture, Messages.AlreadyInstalled, dep.Id));
                            // already have a dependency so move on
                            continue;
                        }
                    }

                    // get all the packages that match this dependency
                    var dependentPackageItem = request.GetPackageById(dep.Id, request, minimumVersion: minVersion, maximumVersion: maxVersion, minInclusive: dep.DependencyVersion.IsMinInclusive, maxInclusive: dep.DependencyVersion.IsMaxInclusive).ToArray();

                    if (dependentPackageItem.Length == 0)
                    {
                        request.WriteError(ErrorCategory.ObjectNotFound, dep.Id, Constants.Messages.UnableToFindDependencyPackage, dep.Id);

                        break;
                    }

                    // Get the package that is the latest version
                    yield return dependentPackageItem.OrderByDescending(each => each.Version).FirstOrDefault();

                    processedDependencies.Add(depKey);
                }
            }
        }