Example #1
0
        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);
            }
        }
Example #2
0
        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);
        }
Example #3
0
        // 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());
        }