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); } }
// 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()); }
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); } } } }