private void ProcessResourceNameParameterSet()
        {
            if (!MyInvocation.BoundParameters.ContainsKey(nameof(Name)))
            {
                // only cases where Name is allowed to not be specified is if Type or Tag parameters are
                if (!MyInvocation.BoundParameters.ContainsKey(nameof(Type)) && !MyInvocation.BoundParameters.ContainsKey(nameof(Tag)))
                {
                    ThrowTerminatingError(
                        new ErrorRecord(
                            new PSInvalidOperationException("Name parameter must be provided."),
                            "NameParameterNotProvided",
                            ErrorCategory.InvalidOperation,
                            this));
                }

                Name = new string[] { "*" };
            }

            Name = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard);

            foreach (string error in errorMsgs)
            {
                WriteError(new ErrorRecord(
                               new PSInvalidOperationException(error),
                               "ErrorFilteringNamesForUnsupportedWildcards",
                               ErrorCategory.InvalidArgument,
                               this));
            }

            // this catches the case where Name wasn't passed in as null or empty,
            // but after filtering out unsupported wildcard names there are no elements left in namesToSearch
            if (Name.Length == 0)
            {
                return;
            }

            List <PSResourceInfo> foundPackages = new List <PSResourceInfo>();

            foreach (PSResourceInfo package in _findHelper.FindByResourceName(
                         Name,
                         Type,
                         Version,
                         Prerelease,
                         Tag,
                         Repository,
                         Credential,
                         IncludeDependencies))
            {
                foundPackages.Add(package);
            }

            foreach (var uniquePackageVersion in foundPackages.GroupBy(
                         m => new { m.Name, m.Version, m.Repository }).Select(
                         group => group.First()).ToList())
            {
                WriteObject(uniquePackageVersion);
            }
        }
Exemple #2
0
        // This method calls iterates through repositories (by priority order) to search for the pkgs to install
        private List <PSResourceInfo> ProcessRepositories(
            string[] repository,
            bool trustRepository,
            PSCredential credential,
            bool skipDependencyCheck)
        {
            var listOfRepositories = RepositorySettings.Read(repository, out string[] _);
            var yesToAll           = false;
            var noToAll            = false;

            var findHelper = new FindHelper(_cancellationToken, _cmdletPassedIn);
            List <PSResourceInfo> allPkgsInstalled = new List <PSResourceInfo>();

            foreach (var repo in listOfRepositories)
            {
                // If no more packages to install, then return
                if (!_pkgNamesToInstall.Any())
                {
                    return(allPkgsInstalled);
                }

                string repoName = repo.Name;
                _cmdletPassedIn.WriteVerbose(string.Format("Attempting to search for packages in '{0}'", repoName));

                // Source is only trusted if it's set at the repository level to be trusted, -TrustRepository flag is true, -Force flag is true
                // OR the user issues trust interactively via console.
                var sourceTrusted = true;
                if (repo.Trusted == false && !trustRepository && !_force)
                {
                    _cmdletPassedIn.WriteVerbose("Checking if untrusted repository should be used");

                    if (!(yesToAll || noToAll))
                    {
                        // Prompt for installation of package from untrusted repository
                        var message = string.Format(CultureInfo.InvariantCulture, MsgInstallUntrustedPackage, repoName);
                        sourceTrusted = _cmdletPassedIn.ShouldContinue(message, MsgRepositoryNotTrusted, true, ref yesToAll, ref noToAll);
                    }
                }

                if (!sourceTrusted && !yesToAll)
                {
                    continue;
                }

                _cmdletPassedIn.WriteVerbose("Untrusted repository accepted as trusted source.");

                // If it can't find the pkg in one repository, it'll look for it in the next repo in the list
                var isLocalRepo = repo.Url.AbsoluteUri.StartsWith(Uri.UriSchemeFile + Uri.SchemeDelimiter, StringComparison.OrdinalIgnoreCase);

                // Finds parent packages and dependencies
                IEnumerable <PSResourceInfo> pkgsFromRepoToInstall = findHelper.FindByResourceName(
                    name: _pkgNamesToInstall.ToArray(),
                    type: ResourceType.None,
                    version: _versionRange != null ? _versionRange.OriginalString : null,
                    prerelease: _prerelease,
                    tag: null,
                    repository: new string[] { repoName },
                    credential: credential,
                    includeDependencies: !skipDependencyCheck);

                if (!pkgsFromRepoToInstall.Any())
                {
                    _cmdletPassedIn.WriteVerbose(string.Format("None of the specified resources were found in the '{0}' repository.", repoName));
                    // Check in the next repository
                    continue;
                }

                // Select the first package from each name group, which is guaranteed to be the latest version.
                // We should only have one version returned for each package name
                // e.g.:
                // PackageA (version 1.0)
                // PackageB (version 2.0)
                // PackageC (version 1.0)
                pkgsFromRepoToInstall = pkgsFromRepoToInstall.GroupBy(
                    m => new { m.Name }).Select(
                    group => group.First()).ToList();

                // Check to see if the pkgs (including dependencies) are already installed (ie the pkg is installed and the version satisfies the version range provided via param)
                if (!_reinstall)
                {
                    pkgsFromRepoToInstall = FilterByInstalledPkgs(pkgsFromRepoToInstall);
                }

                if (!pkgsFromRepoToInstall.Any())
                {
                    continue;
                }

                List <PSResourceInfo> pkgsInstalled = InstallPackage(
                    pkgsFromRepoToInstall,
                    repo.Url.AbsoluteUri,
                    credential,
                    isLocalRepo);

                foreach (PSResourceInfo pkg in pkgsInstalled)
                {
                    _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase));
                }

                allPkgsInstalled.AddRange(pkgsInstalled);
            }

            // At this only package names left were those which could not be found in registered repositories
            foreach (string pkgName in _pkgNamesToInstall)
            {
                var message = String.Format("Package '{0}' with requested version range {1} could not be installed as it was not found in any registered repositories",
                                            pkgName,
                                            _versionRange.ToString());
                var ex = new ArgumentException(message);
                var ResourceNotFoundError = new ErrorRecord(ex, "ResourceNotFoundError", ErrorCategory.ObjectNotFound, null);
                _cmdletPassedIn.WriteError(ResourceNotFoundError);
            }

            return(allPkgsInstalled);
        }
        /// <Summary>
        /// This method performs a number of functions on the list of resource package names to update.
        ///  - Processes the name list for wild card characters.
        ///  - Writes errors for names with unsupported wild characters.
        ///  - Finds installed packages that match the names list.
        ///  - Finds repository packages that match the names list and update version.
        ///  - Compares installed packages and repository search results with name list.
        ///  - Returns a final list of packages for reinstall, that meet update criteria.
        /// </Summary>
        private string[] ProcessPackageNames(
            string[] namesToProcess,
            VersionRange versionRange)
        {
            namesToProcess = Utils.ProcessNameWildcards(
                pkgNames: namesToProcess,
                errorMsgs: out string[] errorMsgs,
                isContainWildcard: out bool _);

            foreach (string error in errorMsgs)
            {
                WriteError(new ErrorRecord(
                               new PSInvalidOperationException(error),
                               "ErrorFilteringNamesForUnsupportedWildcards",
                               ErrorCategory.InvalidArgument,
                               this));
            }

            // This catches the case where namesToProcess wasn't passed in as null or empty,
            // but after filtering out unsupported wildcard names there are no elements left in namesToProcess.
            if (namesToProcess.Length == 0)
            {
                return(Utils.EmptyStrArray);
            }

            if (String.Equals(namesToProcess[0], "*", StringComparison.InvariantCultureIgnoreCase))
            {
                WriteVerbose("Package names were detected to be (or contain an element equal to): '*', so all packages will be updated");
            }

            // Get all installed packages selected for updating.
            GetHelper getHelper         = new GetHelper(cmdletPassedIn: this);
            var       installedPackages = new Dictionary <string, PSResourceInfo>(StringComparer.InvariantCultureIgnoreCase);

            foreach (var installedPackage in getHelper.GetPackagesFromPath(
                         name: namesToProcess,
                         versionRange: VersionRange.All,
                         pathsToSearch: Utils.GetAllResourcePaths(this, Scope)))
            {
                if (!installedPackages.ContainsKey(installedPackage.Name))
                {
                    installedPackages.Add(installedPackage.Name, installedPackage);
                }
            }

            if (installedPackages.Count is 0)
            {
                WriteWarning($"No installed packages were found with name '{string.Join(",", namesToProcess)}' in scope '{Scope}'. First install package using 'Install-PSResource'.");
                return(Utils.EmptyStrArray);
            }

            // Find all packages selected for updating in provided repositories.
            var repositoryPackages = new Dictionary <string, PSResourceInfo>(StringComparer.InvariantCultureIgnoreCase);

            foreach (var foundResource in _findHelper.FindByResourceName(
                         name: installedPackages.Keys.ToArray(),
                         type: ResourceType.None,
                         version: Version,
                         prerelease: Prerelease,
                         tag: null,
                         repository: Repository,
                         credential: Credential,
                         includeDependencies: !SkipDependencyCheck))
            {
                if (!repositoryPackages.ContainsKey(foundResource.Name))
                {
                    repositoryPackages.Add(foundResource.Name, foundResource);
                }
            }

            // Check if named package is installed or can be found in the repositories.
            foreach (var nameToProcess in namesToProcess)
            {
                if (!WildcardPattern.ContainsWildcardCharacters(nameToProcess))
                {
                    if (!installedPackages.ContainsKey(nameToProcess))
                    {
                        WriteWarning(
                            $"Package '{nameToProcess}' not installed in scope '{Scope}'. First install package using 'Install-PSResource'.");
                    }
                    else if (!repositoryPackages.ContainsKey(nameToProcess))
                    {
                        WriteWarning(
                            $"Installed package '{nameToProcess}':'{Version}' was not found in repositories and cannot be updated.");
                    }
                }
            }

            // Create list of packages to update.
            List <string> namesToUpdate = new List <string>();

            foreach (PSResourceInfo repositoryPackage in repositoryPackages.Values)
            {
                if (!installedPackages.TryGetValue(repositoryPackage.Name, out PSResourceInfo installedPackage))
                {
                    continue;
                }

                // If the current package is out of range, install it with the correct version.
                if (!NuGetVersion.TryParse(installedPackage.Version.ToString(), out NuGetVersion installedVersion))
                {
                    WriteWarning($"Cannot parse nuget version in installed package '{installedPackage.Name}'. Cannot update package.");
                    continue;
                }

                if ((versionRange == VersionRange.All && repositoryPackage.Version > installedPackage.Version) ||
                    !versionRange.Satisfies(installedVersion))
                {
                    namesToUpdate.Add(repositoryPackage.Name);
                }
                else
                {
                    WriteVerbose($"Installed package {repositoryPackage.Name} is up to date.");
                }
            }

            return(namesToUpdate.ToArray());
        }
Exemple #4
0
        private void ProcessResourceNameParameterSet()
        {
            if (!MyInvocation.BoundParameters.ContainsKey(nameof(Name)))
            {
                // TODO: Add support for Tag and Type parameters without Name parameter being specified.
                if (MyInvocation.BoundParameters.ContainsKey(nameof(Type)) || MyInvocation.BoundParameters.ContainsKey(nameof(Tag)))
                {
                    ThrowTerminatingError(
                        new ErrorRecord(
                            new PSNotImplementedException("Search by Tag or Type parameter is not yet implemented."),
                            "TagTypeSearchNotYetImplemented",
                            ErrorCategory.NotImplemented,
                            this));
                }

                ThrowTerminatingError(
                    new ErrorRecord(
                        new PSInvalidOperationException("Name parameter must be provided."),
                        "NameParameterNotProvided",
                        ErrorCategory.InvalidOperation,
                        this));
            }

            Name = Utils.FilterOutWildcardNames(Name, out string[] errorMsgs);
            foreach (string error in errorMsgs)
            {
                WriteError(new ErrorRecord(
                               new PSInvalidOperationException(error),
                               "ErrorFilteringNamesForUnsupportedWildcards",
                               ErrorCategory.InvalidArgument,
                               this));
            }

            if (Name.Length == 0)
            {
                return;
            }

            FindHelper            findHelper    = new FindHelper(_cancellationToken, this);
            List <PSResourceInfo> foundPackages = new List <PSResourceInfo>();

            foreach (PSResourceInfo package in findHelper.FindByResourceName(
                         Name,
                         Type,
                         Version,
                         Prerelease,
                         Tag,
                         Repository,
                         Credential,
                         IncludeDependencies))
            {
                foundPackages.Add(package);
            }

            foreach (var uniquePackageVersion in foundPackages.GroupBy(
                         m => new { m.Name, m.Version }).Select(
                         group => group.First()).ToList())
            {
                WriteObject(uniquePackageVersion);
            }
        }
        // This method calls iterates through repositories (by priority order) to search for the pkgs to install
        public void ProcessRepositories(string[] packageNames, string[] repository, bool trustRepository, PSCredential credential)
        {
            var           listOfRepositories           = RepositorySettings.Read(repository, out string[] _);
            List <string> packagesToInstall            = packageNames.ToList();
            var           yesToAll                     = false;
            var           noToAll                      = false;
            var           repositoryIsNotTrusted       = "Untrusted repository";
            var           queryInstallUntrustedPackage = "You are installing the modules from an untrusted repository. If you trust this repository, change its Trusted value by running the Set-PSResourceRepository cmdlet. Are you sure you want to install the PSresource from '{0}' ?";

            foreach (var repo in listOfRepositories)
            {
                // If no more packages to install, then return
                if (!packagesToInstall.Any())
                {
                    return;
                }

                var    sourceTrusted = false;
                string repoName      = repo.Name;
                _cmdletPassedIn.WriteDebug(string.Format("Attempting to search for packages in '{0}'", repoName));

                // Source is only trusted if it's set at the repository level to be trusted, -TrustRepository flag is true, -Force flag is true
                // OR the user issues trust interactively via console.
                if (repo.Trusted == false && !trustRepository && !_force)
                {
                    _cmdletPassedIn.WriteDebug("Checking if untrusted repository should be used");

                    if (!(yesToAll || noToAll))
                    {
                        // Prompt for installation of package from untrusted repository
                        var message = string.Format(CultureInfo.InvariantCulture, queryInstallUntrustedPackage, repoName);
                        sourceTrusted = _cmdletPassedIn.ShouldContinue(message, repositoryIsNotTrusted, true, ref yesToAll, ref noToAll);
                    }
                }
                else
                {
                    sourceTrusted = true;
                }

                if (sourceTrusted || yesToAll)
                {
                    _cmdletPassedIn.WriteDebug("Untrusted repository accepted as trusted source.");

                    // If it can't find the pkg in one repository, it'll look for it in the next repo in the list
                    var isLocalRepo = repo.Url.AbsoluteUri.StartsWith(Uri.UriSchemeFile + Uri.SchemeDelimiter, StringComparison.OrdinalIgnoreCase);


                    var findHelper = new FindHelper(_cancellationToken, _cmdletPassedIn);
                    // Finds parent packages and dependencies
                    IEnumerable <PSResourceInfo> pkgsFromRepoToInstall = findHelper.FindByResourceName(
                        name: packageNames,
                        type: ResourceType.None,
                        version: _versionRange != null ? _versionRange.OriginalString : null,
                        prerelease: _prerelease,
                        tag: null,
                        repository: new string[] { repoName },
                        credential: credential,
                        includeDependencies: true);

                    foreach (PSResourceInfo a in pkgsFromRepoToInstall)
                    {
                        var test = a;
                        _cmdletPassedIn.WriteVerbose(a.Version.ToString());
                    }

                    // Select the first package from each name group, which is guaranteed to be the latest version.
                    // We should only have one version returned for each package name
                    // e.g.:
                    // PackageA (version 1.0)
                    // PackageB (version 2.0)
                    // PackageC (version 1.0)
                    pkgsFromRepoToInstall = pkgsFromRepoToInstall.GroupBy(
                        m => new { m.Name }).Select(
                        group => group.First()).ToList();

                    if (!pkgsFromRepoToInstall.Any())
                    {
                        _cmdletPassedIn.WriteVerbose(string.Format("None of the specified resources were found in the '{0}' repository.", repoName));
                        // Check in the next repository
                        continue;
                    }

                    // Check to see if the pkgs (including dependencies) are already installed (ie the pkg is installed and the version satisfies the version range provided via param)
                    if (!_reinstall)
                    {
                        // Removes all of the names that are already installed from the list of names to search for
                        pkgsFromRepoToInstall = FilterByInstalledPkgs(pkgsFromRepoToInstall);
                    }

                    if (!pkgsFromRepoToInstall.Any())
                    {
                        continue;
                    }

                    List <string> pkgsInstalled = InstallPackage(pkgsFromRepoToInstall, repoName, repo.Url.AbsoluteUri, credential, isLocalRepo);

                    foreach (string name in pkgsInstalled)
                    {
                        packagesToInstall.Remove(name);
                    }
                }
            }
        }