protected override void ProcessRecord() { WriteVerbose("Entering GetPSResource"); var namesToSearch = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool _); 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 in BeginProcessing() there are no elements left in Name. if (namesToSearch.Length == 0) { return; } // SelectPrereleaseOnly is false because we want both stable and prerelease versions all the time.. GetHelper getHelper = new GetHelper(this); foreach (PSResourceInfo pkg in getHelper.GetPackagesFromPath( name: namesToSearch, versionRange: _versionRange, pathsToSearch: _pathsToSearch, selectPrereleaseOnly: false)) { WriteObject(pkg); } }
private bool DetectClobber(string pkgName, Hashtable parsedMetadataHashtable) { // Get installed modules, then get all possible paths bool foundClobber = false; GetHelper getHelper = new GetHelper(_cmdletPassedIn); // selectPrereleaseOnly is false because even if Prerelease is true we want to include both stable and prerelease, never select prerelease only. IEnumerable <PSResourceInfo> pkgsAlreadyInstalled = getHelper.GetPackagesFromPath( name: new string[] { "*" }, versionRange: VersionRange.All, pathsToSearch: _pathsToSearch, selectPrereleaseOnly: false); // user parsed metadata hash List <string> listOfCmdlets = new List <string>(); foreach (var cmdletName in parsedMetadataHashtable["CmdletsToExport"] as object[]) { listOfCmdlets.Add(cmdletName as string); } foreach (var pkg in pkgsAlreadyInstalled) { List <string> duplicateCmdlets = new List <string>(); List <string> duplicateCmds = new List <string>(); // See if any of the cmdlets or commands in the pkg we're trying to install exist within a package that's already installed if (pkg.Includes.Cmdlet != null && pkg.Includes.Cmdlet.Any()) { duplicateCmdlets = listOfCmdlets.Where(cmdlet => pkg.Includes.Cmdlet.Contains(cmdlet)).ToList(); } if (pkg.Includes.Command != null && pkg.Includes.Command.Any()) { duplicateCmds = listOfCmdlets.Where(commands => pkg.Includes.Command.Contains(commands, StringComparer.InvariantCultureIgnoreCase)).ToList(); } if (duplicateCmdlets.Any() || duplicateCmds.Any()) { duplicateCmdlets.AddRange(duplicateCmds); var errMessage = string.Format( "{1} package could not be installed with error: The following commands are already available on this system: '{0}'. This module '{1}' may override the existing commands. If you still want to install this module '{1}', remove the -NoClobber parameter.", String.Join(", ", duplicateCmdlets), pkgName); var ex = new ArgumentException(errMessage); var noClobberError = new ErrorRecord(ex, "CommandAlreadyExists", ErrorCategory.ResourceExists, null); _cmdletPassedIn.WriteError(noClobberError); _pkgNamesToInstall.RemoveAll(x => x.Equals(pkgName, StringComparison.InvariantCultureIgnoreCase)); foundClobber = true; return(foundClobber); } } return(foundClobber); }
// Check if any of the pkg versions are already installed, if they are we'll remove them from the list of packages to install private IEnumerable <PSResourceInfo> FilterByInstalledPkgs(IEnumerable <PSResourceInfo> packages) { // Create list of installation paths to search. List <string> _pathsToSearch = new List <string>(); // _pathsToInstallPkg will only contain the paths specified within the -Scope param (if applicable) // _pathsToSearch will contain all resource package subdirectories within _pathsToInstallPkg path locations // e.g.: // ./InstallPackagePath1/PackageA // ./InstallPackagePath1/PackageB // ./InstallPackagePath2/PackageC // ./InstallPackagePath3/PackageD foreach (var path in _pathsToInstallPkg) { _pathsToSearch.AddRange(Utils.GetSubDirectories(path)); } var filteredPackages = new Dictionary <string, PSResourceInfo>(); foreach (var pkg in packages) { filteredPackages.Add(pkg.Name, pkg); } GetHelper getHelper = new GetHelper(_cmdletPassedIn); // Get currently installed packages. // selectPrereleaseOnly is false because even if Prerelease is true we want to include both stable and prerelease, never select prerelease only. IEnumerable <PSResourceInfo> pkgsAlreadyInstalled = getHelper.GetPackagesFromPath( name: filteredPackages.Keys.ToArray(), versionRange: _versionRange, pathsToSearch: _pathsToSearch, selectPrereleaseOnly: false); if (!pkgsAlreadyInstalled.Any()) { return(packages); } // Remove from list package versions that are already installed. foreach (PSResourceInfo pkg in pkgsAlreadyInstalled) { _cmdletPassedIn.WriteWarning( string.Format("Resource '{0}' with version '{1}' is already installed. If you would like to reinstall, please run the cmdlet again with the -Reinstall parameter", pkg.Name, pkg.Version)); filteredPackages.Remove(pkg.Name); _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); } return(filteredPackages.Values.ToArray()); }
/// <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()); }