From a970dc5471dd1b349ef733fe51652c8ac489fcca Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Wed, 20 Jul 2022 13:14:11 -0700 Subject: [PATCH 1/7] Remove unneeded IEnumerable interfaces --- src/code/FindHelper.cs | 81 ++++++++++++++++++++--------------- src/code/FindPSResource.cs | 35 ++++++--------- src/code/GetPSResource.cs | 6 +-- src/code/InstallHelper.cs | 60 +++++++++++++------------- src/code/PublishPSResource.cs | 15 +++++-- 5 files changed, 103 insertions(+), 94 deletions(-) diff --git a/src/code/FindHelper.cs b/src/code/FindHelper.cs index 916e5a793..ee25abb56 100644 --- a/src/code/FindHelper.cs +++ b/src/code/FindHelper.cs @@ -70,7 +70,7 @@ public FindHelper(CancellationToken cancellationToken, PSCmdlet cmdletPassedIn) #region Public methods - public IEnumerable FindByResourceName( + public List FindByResourceName( string[] name, ResourceType type, string version, @@ -87,13 +87,16 @@ public IEnumerable FindByResourceName( _credential = credential; _includeDependencies = includeDependencies; - Dbg.Assert(name.Length != 0, "Name length cannot be 0"); + List foundPackages = new List(); - _pkgsLeftToFind = name.ToList(); + if (name.Length == 0) + { + return foundPackages; + } - List repositoriesToSearch; + _pkgsLeftToFind = name.ToList(); - //determine if repository array of names of repositories input to be searched contains wildcard + // Error out if repository array of names to be searched contains wildcards. if (repository != null) { repository = Utils.ProcessNameWildcards(repository, out string[] errorMsgs, out _repositoryNameContainsWildcard); @@ -107,6 +110,8 @@ public IEnumerable FindByResourceName( } } + // Get repositories to search. + List repositoriesToSearch; try { repositoriesToSearch = RepositorySettings.Read(repository, out string[] errorList); @@ -126,11 +131,12 @@ public IEnumerable FindByResourceName( "ErrorLoadingRepositoryStoreFile", ErrorCategory.InvalidArgument, this)); - yield break; + + return foundPackages; } - // loop through repositoriesToSearch and if PSGallery or PoshTestGallery add its Scripts endpoint repo - // to list with same priority as PSGallery repo + // Loop through repositoriesToSearch and if PSGallery or PoshTestGallery add its Scripts endpoint repo + // to list with same priority as PSGallery repo. // This special casing is done to handle PSGallery and PoshTestGallery having 2 endpoints currently for different resources. for (int i = 0; i < repositoriesToSearch.Count; i++) { @@ -185,9 +191,11 @@ public IEnumerable FindByResourceName( repositoryUri: repositoriesToSearch[i].Uri, repositoryCredentialInfo: repositoriesToSearch[i].CredentialInfo)) { - yield return pkg; + foundPackages.Add(pkg); } } + + return foundPackages; } #endregion @@ -204,7 +212,7 @@ private IEnumerable SearchFromRepository( SearchFilter filter; SourceCacheContext context; - // file based Uri scheme + // File based Uri scheme. if (repositoryUri.Scheme == Uri.UriSchemeFile) { FindLocalPackagesResourceV2 localResource = new FindLocalPackagesResourceV2(repositoryUri.ToString()); @@ -225,16 +233,16 @@ private IEnumerable SearchFromRepository( yield break; } - // check if ADOFeed- for which searching for Name with wildcard has a different logic flow + // Check if ADOFeed- for which searching for Name with wildcard has a different logic flow. if (repositoryUri.ToString().Contains("pkgs.")) { _isADOFeedRepository = true; } - // HTTP, HTTPS, FTP Uri schemes (only other Uri schemes allowed by RepositorySettings.Read() API) + // HTTP, HTTPS, FTP Uri schemes (only other Uri schemes allowed by RepositorySettings.Read() API). PackageSource source = new PackageSource(repositoryUri.ToString()); - // Explicitly passed in Credential takes precedence over repository CredentialInfo + // Explicitly passed in Credential takes precedence over repository CredentialInfo. if (_credential != null) { string password = new NetworkCredential(string.Empty, _credential.Password).Password; @@ -253,7 +261,7 @@ private IEnumerable SearchFromRepository( _cmdletPassedIn.WriteVerbose("credential successfully read from vault and set for repository: " + repositoryName); } - // GetCoreV3() API is able to handle V2 and V3 repository endpoints + // GetCoreV3() API is able to handle V2 and V3 repository endpoints. var provider = FactoryExtensionsV3.GetCoreV3(NuGet.Protocol.Core.Types.Repository.Provider); SourceRepository repository = new SourceRepository(source, provider); resourceSearch = null; @@ -351,7 +359,7 @@ private IEnumerable FindFromPackageSourceSearchAPI( if (!pkgName.Contains("*")) { // case: searching for specific package name i.e "Carbon" - IEnumerable retrievedPkgs = null; + IEnumerable retrievedPkgs; try { // GetMetadataAsync() API returns all versions for a specific non-wildcard package name @@ -372,23 +380,24 @@ private IEnumerable FindFromPackageSourceSearchAPI( { _cmdletPassedIn.WriteWarning(String.Format("Error receiving package from PSGallery. To check if this is due to a PSGallery outage check: https://aka.ms/psgallerystatus . Specific error: {0}", ex.Message)); } + + yield break; } catch (Exception e) { Utils.WriteVerboseOnCmdlet(_cmdletPassedIn, "FindHelper MetadataAsync: error receiving package: " + e.Message); + yield break; } - if (retrievedPkgs == null || retrievedPkgs.Count() == 0) + // Iterate through any packages found in repository. + bool packagesFound = false; + foreach (var pkg in retrievedPkgs) { - _cmdletPassedIn.WriteVerbose(string.Format("'{0}' could not be found in repository '{1}'", pkgName, repositoryName)); - yield break; + foundPackagesMetadata.Add(pkg); + if (!packagesFound) { packagesFound = true; } } - foundPackagesMetadata.AddRange(retrievedPkgs.ToList()); - - // _pkgsLeftToFind.Remove(pkgName); - - if (!_repositoryNameContainsWildcard) + if (packagesFound && !_repositoryNameContainsWildcard) { _pkgsLeftToFind.Remove(pkgName); } @@ -404,8 +413,9 @@ private IEnumerable FindFromPackageSourceSearchAPI( this)); yield break; } - // case: searching for name containing wildcard i.e "Carbon.*" - IEnumerable wildcardPkgs = null; + + // Case: searching for name containing wildcard i.e "Carbon.*". + List wildcardPkgs; try { // SearchAsync() API returns the latest version only for all packages that match the wild-card name @@ -415,11 +425,13 @@ private IEnumerable FindFromPackageSourceSearchAPI( skip: 0, take: SearchAsyncMaxTake, log: NullLogger.Instance, - cancellationToken: _cancellationToken).GetAwaiter().GetResult(); - if (wildcardPkgs.Count() > SearchAsyncMaxReturned) + cancellationToken: _cancellationToken).GetAwaiter().GetResult().ToList(); + + if (wildcardPkgs.Count > SearchAsyncMaxReturned) { - // get the rest of the packages - wildcardPkgs = wildcardPkgs.Concat(pkgSearchResource.SearchAsync( + // Get the rest of the packages. + wildcardPkgs.AddRange( + pkgSearchResource.SearchAsync( searchTerm: pkgName, filters: searchFilter, skip: SearchAsyncMaxTake, @@ -447,12 +459,13 @@ private IEnumerable FindFromPackageSourceSearchAPI( // filter additionally because NuGet wildcard search API returns more than we need // perhaps validate in Find-PSResource, and use debugassert here? WildcardPattern nameWildcardPattern = new WildcardPattern(pkgName, WildcardOptions.IgnoreCase); - foundPackagesMetadata.AddRange(wildcardPkgs.Where( - p => nameWildcardPattern.IsMatch(p.Identity.Id)).ToList()); + foundPackagesMetadata.AddRange( + wildcardPkgs.Where( + p => nameWildcardPattern.IsMatch(p.Identity.Id))); if (!_repositoryNameContainsWildcard) { - // if the Script Uri endpoint still needs to be searched, don't remove the wildcard name from _pkgsLeftToFind + // If the Script Uri endpoint still needs to be searched, don't remove the wildcard name from _pkgsLeftToFind // PSGallery + Type == null -> M, S // PSGallery + Type == M -> M // PSGallery + Type == S -> S (but PSGallery would be skipped early on, only PSGalleryScripts would be checked) @@ -462,7 +475,7 @@ private IEnumerable FindFromPackageSourceSearchAPI( if (String.Equals(repositoryName, _psGalleryRepoName, StringComparison.InvariantCultureIgnoreCase) || String.Equals(repositoryName, _poshTestGalleryRepoName, StringComparison.InvariantCultureIgnoreCase)) { - if (foundPackagesMetadata.Any() && _type != ResourceType.None) + if (foundPackagesMetadata.Count > 0 && _type != ResourceType.None) { _pkgsLeftToFind.Remove(pkgName); } @@ -477,7 +490,7 @@ private IEnumerable FindFromPackageSourceSearchAPI( if (foundPackagesMetadata.Count == 0) { // no need to attempt to filter further - _cmdletPassedIn.WriteVerbose("no packages found"); + _cmdletPassedIn.WriteVerbose($"No packages found in repository: {repositoryName}."); yield break; } diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index b99b520c5..f3def79da 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -217,24 +217,19 @@ private void ProcessResourceNameParameterSet() return; } - List foundPackages = new List(); - - foreach (PSResourceInfo package in _findHelper.FindByResourceName( - Name, - Type, - Version, - Prerelease, - Tag, - Repository, - Credential, - IncludeDependencies)) - { - foundPackages.Add(package); - } + List foundPackages = _findHelper.FindByResourceName( + name: Name, + type: Type, + version: Version, + prerelease: Prerelease, + tag: Tag, + repository: Repository, + credential: Credential, + includeDependencies: IncludeDependencies); foreach (var uniquePackageVersion in foundPackages.GroupBy( m => new {m.Name, m.Version, m.Repository}).Select( - group => group.First()).ToList()) + group => group.First())) { WriteObject(uniquePackageVersion); } @@ -292,21 +287,15 @@ private void ProcessCommandOrDscParameterSet(bool isSearchingForCommands) moduleNamesToSearch = new string[] {"*"}; } - List foundPackages = new List(); - - foreach (PSResourceInfo package in _findHelper.FindByResourceName( + List foundPackages = _findHelper.FindByResourceName( name: moduleNamesToSearch, - // provide type so Scripts endpoint for PSGallery won't be searched type: isSearchingForCommands? ResourceType.Command : ResourceType.DscResource, version: Version, prerelease: Prerelease, tag: Tag, repository: Repository, credential: Credential, - includeDependencies: IncludeDependencies)) - { - foundPackages.Add(package); - } + includeDependencies: IncludeDependencies); // if a single package contains multiple commands we are interested in, return a unique entry for each: // Command1 , PackageA diff --git a/src/code/GetPSResource.cs b/src/code/GetPSResource.cs index 0db720a5f..453555d53 100644 --- a/src/code/GetPSResource.cs +++ b/src/code/GetPSResource.cs @@ -127,15 +127,15 @@ protected override void ProcessRecord() 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 + // 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); - // selectPrereleaseOnly is false because we want both stable and prerelease versions all the time. foreach (PSResourceInfo pkg in getHelper.GetPackagesFromPath( name: namesToSearch, versionRange: _versionRange, diff --git a/src/code/InstallHelper.cs b/src/code/InstallHelper.cs index 35fea684c..767cfefbf 100644 --- a/src/code/InstallHelper.cs +++ b/src/code/InstallHelper.cs @@ -192,20 +192,19 @@ private List ProcessRepositories( var isLocalRepo = repo.Uri.AbsoluteUri.StartsWith(Uri.UriSchemeFile + Uri.SchemeDelimiter, StringComparison.OrdinalIgnoreCase); // Finds parent packages and dependencies - IEnumerable pkgsFromRepoToInstall = findHelper.FindByResourceName( + List pkgsFromRepoToInstall = findHelper.FindByResourceName( name: _pkgNamesToInstall.ToArray(), type: ResourceType.None, - version: _versionRange != null ? _versionRange.OriginalString : null, + version: _versionRange?.OriginalString, prerelease: _prerelease, tag: null, repository: new string[] { repoName }, credential: credential, includeDependencies: !skipDependencyCheck); - if (!pkgsFromRepoToInstall.Any()) + if (pkgsFromRepoToInstall.Count == 0) { _cmdletPassedIn.WriteVerbose(string.Format("None of the specified resources were found in the '{0}' repository.", repoName)); - // Check in the next repository continue; } @@ -261,54 +260,53 @@ private List ProcessRepositories( } // 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 FilterByInstalledPkgs(IEnumerable packages) + private List FilterByInstalledPkgs(List packages) { - // Create list of installation paths to search. - List _pathsToSearch = new List(); - // _pathsToInstallPkg will only contain the paths specified within the -Scope param (if applicable) - // _pathsToSearch will contain all resource package subdirectories within _pathsToInstallPkg path locations + // Package install paths. + // _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(); + // Get package names + var packageNames = new HashSet(StringComparer.CurrentCultureIgnoreCase); foreach (var pkg in packages) { - filteredPackages.Add(pkg.Name, pkg); + packageNames.Add(pkg.Name); } - 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 pkgsAlreadyInstalled = getHelper.GetPackagesFromPath( - name: filteredPackages.Keys.ToArray(), + // SelectPrereleaseOnly is false because even if Prerelease is true we want to include both stable and prerelease, never select prerelease only. + var getHelper = new GetHelper(_cmdletPassedIn); + var installedPackageNames = new HashSet(StringComparer.CurrentCultureIgnoreCase); + foreach (var installedPkg in getHelper.GetPackagesFromPath( + name: packageNames.ToArray(), versionRange: _versionRange, pathsToSearch: _pathsToSearch, - selectPrereleaseOnly: false); - if (!pkgsAlreadyInstalled.Any()) + selectPrereleaseOnly: false)) { - return packages; + installedPackageNames.Add(installedPkg.Name); } - // Remove from list package versions that are already installed. - foreach (PSResourceInfo pkg in pkgsAlreadyInstalled) + if (installedPackageNames.Count is 0) { - _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)); + return packages; + } - filteredPackages.Remove(pkg.Name); - _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); + // Return only packages that are not already installed. + var filteredPackages = new List(); + foreach (var pkg in packages) + { + if (!installedPackageNames.Contains(pkg.Name)) + { + filteredPackages.Add(pkg); + } } - return filteredPackages.Values.ToArray(); + return filteredPackages; } private List InstallPackage( diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index 752255eae..7b3eee131 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -885,9 +885,17 @@ private bool CheckDependenciesExist(Hashtable dependencies, string repositoryNam FindHelper findHelper = new FindHelper(_cancellationToken, this); bool depPrerelease = depVersion.Contains("-"); - var repository = new[] { repositoryName }; - var dependencyFound = findHelper.FindByResourceName(depName, ResourceType.Module, depVersion, depPrerelease, null, repository, Credential, false); - if (dependencyFound == null || !dependencyFound.Any()) + var foundDependencies = findHelper.FindByResourceName( + name: depName, + type: ResourceType.Module, + version: depVersion, + prerelease: depPrerelease, + tag: null, + repository: new[] { repositoryName }, + credential: Credential, + includeDependencies: false); + + if (foundDependencies.Count > 0) { var message = String.Format("Dependency '{0}' was not found in repository '{1}'. Make sure the dependency is published to the repository before publishing this module.", dependency, repositoryName); var ex = new ArgumentException(message); @@ -897,6 +905,7 @@ private bool CheckDependenciesExist(Hashtable dependencies, string repositoryNam return false; } } + return true; } From edbb9f8bbbd903db6359e7b46e361afb09369a84 Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Wed, 20 Jul 2022 16:11:45 -0700 Subject: [PATCH 2/7] Add missing clean up --- src/code/InstallHelper.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/code/InstallHelper.cs b/src/code/InstallHelper.cs index 767cfefbf..829732c44 100644 --- a/src/code/InstallHelper.cs +++ b/src/code/InstallHelper.cs @@ -302,8 +302,14 @@ private List FilterByInstalledPkgs(List packages { if (!installedPackageNames.Contains(pkg.Name)) { + // Add packages that still need to be installed. filteredPackages.Add(pkg); } + else + { + // Remove from list package versions that are already installed. + _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); + } } return filteredPackages; From 58583dbf3904272a469f8096e47b078181ad0551 Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Thu, 21 Jul 2022 15:48:31 -0700 Subject: [PATCH 3/7] Fix always reinstall --- src/code/FindHelper.cs | 103 ++++++++++++++++---------------- src/code/GetHelper.cs | 38 ++++++++++++ src/code/InstallHelper.cs | 38 ++++++------ test/FindPSResource.Tests.ps1 | 2 +- test/UpdatePSResource.Tests.ps1 | 2 +- 5 files changed, 108 insertions(+), 75 deletions(-) diff --git a/src/code/FindHelper.cs b/src/code/FindHelper.cs index ee25abb56..3c3d8abdb 100644 --- a/src/code/FindHelper.cs +++ b/src/code/FindHelper.cs @@ -9,18 +9,14 @@ using NuGet.Protocol.Core.Types; using NuGet.Versioning; using System; -using System.Collections; using System.Collections.Generic; using System.Data; using System.Linq; using System.Management.Automation; using System.Net; using System.Net.Http; -using System.Security; using System.Threading; -using Dbg = System.Diagnostics.Debug; - namespace Microsoft.PowerShell.PowerShellGet.Cmdlets { /// @@ -618,72 +614,75 @@ SourceCacheContext sourceCacheContext { foreach(var dep in currentPkg.Dependencies) { - IEnumerable depPkgs = packageMetadataResource.GetMetadataAsync( + List depPkgs = packageMetadataResource.GetMetadataAsync( packageId: dep.Name, includePrerelease: _prerelease, includeUnlisted: false, sourceCacheContext: sourceCacheContext, log: NullLogger.Instance, - token: _cancellationToken).GetAwaiter().GetResult(); + token: _cancellationToken).GetAwaiter().GetResult().ToList(); - if (depPkgs.Count() > 0) + if (depPkgs.Count is 0) { - if (dep.VersionRange == VersionRange.All) - { - // return latest version - IPackageSearchMetadata depPkgLatestVersion = depPkgs.First(); - - if (!PSResourceInfo.TryConvert( - metadataToParse: depPkgLatestVersion, - psGetInfo: out PSResourceInfo depPSResourceInfoPkg, - repositoryName: currentPkg.Repository, - type: currentPkg.Type, - errorMsg: out string errorMsg)) - { - _cmdletPassedIn.WriteError(new ErrorRecord( - new PSInvalidOperationException("Error parsing dependency IPackageSearchMetadata to PSResourceInfo with message: " + errorMsg), - "DependencyIPackageSearchMetadataToPSResourceInfoParsingError", - ErrorCategory.InvalidResult, - this)); - } + continue; + } - thoseToAdd.Add(depPSResourceInfoPkg); - FindDependencyPackagesHelper(depPSResourceInfoPkg, thoseToAdd, packageMetadataResource, sourceCacheContext); - } - else + if (dep.VersionRange == VersionRange.All) + { + // return latest version + IPackageSearchMetadata depPkgLatestVersion = depPkgs.First(); + + if (!PSResourceInfo.TryConvert( + metadataToParse: depPkgLatestVersion, + psGetInfo: out PSResourceInfo depPSResourceInfoPkg, + repositoryName: currentPkg.Repository, + type: currentPkg.Type, + errorMsg: out string errorMsg)) { - List pkgVersionsInRange = depPkgs.Where( - p => dep.VersionRange.Satisfies( - p.Identity.Version, VersionComparer.VersionRelease)).OrderByDescending( - p => p.Identity.Version).ToList(); + _cmdletPassedIn.WriteError(new ErrorRecord( + new PSInvalidOperationException("Error parsing dependency IPackageSearchMetadata to PSResourceInfo with message: " + errorMsg), + "DependencyIPackageSearchMetadataToPSResourceInfoParsingError", + ErrorCategory.InvalidResult, + this)); + } + + thoseToAdd.Add(depPSResourceInfoPkg); + FindDependencyPackagesHelper(depPSResourceInfoPkg, thoseToAdd, packageMetadataResource, sourceCacheContext); + } + else + { + List pkgVersionsInRange = depPkgs.Where( + p => dep.VersionRange.Satisfies( + p.Identity.Version, VersionComparer.VersionRelease)).OrderByDescending( + p => p.Identity.Version).ToList(); - if (pkgVersionsInRange.Count() > 0) + if (pkgVersionsInRange.Count() > 0) + { + IPackageSearchMetadata depPkgLatestInRange = pkgVersionsInRange.First(); + if (depPkgLatestInRange != null) { - IPackageSearchMetadata depPkgLatestInRange = pkgVersionsInRange.First(); - if (depPkgLatestInRange != null) + if (!PSResourceInfo.TryConvert( + metadataToParse: depPkgLatestInRange, + psGetInfo: out PSResourceInfo depPSResourceInfoPkg, + repositoryName: currentPkg.Repository, + type: currentPkg.Type, + errorMsg: out string errorMsg)) { - if (!PSResourceInfo.TryConvert( - metadataToParse: depPkgLatestInRange, - psGetInfo: out PSResourceInfo depPSResourceInfoPkg, - repositoryName: currentPkg.Repository, - type: currentPkg.Type, - errorMsg: out string errorMsg)) - { - _cmdletPassedIn.WriteError(new ErrorRecord( - new PSInvalidOperationException("Error parsing dependency range IPackageSearchMetadata to PSResourceInfo with message: " + errorMsg), - "DependencyRangeIPackageSearchMetadataToPSResourceInfoParsingError", - ErrorCategory.InvalidResult, - this)); - } - - thoseToAdd.Add(depPSResourceInfoPkg); - FindDependencyPackagesHelper(depPSResourceInfoPkg, thoseToAdd, packageMetadataResource, sourceCacheContext); + _cmdletPassedIn.WriteError(new ErrorRecord( + new PSInvalidOperationException("Error parsing dependency range IPackageSearchMetadata to PSResourceInfo with message: " + errorMsg), + "DependencyRangeIPackageSearchMetadataToPSResourceInfoParsingError", + ErrorCategory.InvalidResult, + this)); } + + thoseToAdd.Add(depPSResourceInfoPkg); + FindDependencyPackagesHelper(depPSResourceInfoPkg, thoseToAdd, packageMetadataResource, sourceCacheContext); } } } } } + #endregion } } diff --git a/src/code/GetHelper.cs b/src/code/GetHelper.cs index c96586d40..49b24bc9b 100644 --- a/src/code/GetHelper.cs +++ b/src/code/GetHelper.cs @@ -37,6 +37,44 @@ public GetHelper(PSCmdlet cmdletPassedIn) #region Public methods + /// + /// Retrieves package paths from provided search paths for installed packages + /// by name *and* version. + /// + public IEnumerable GetInstalledPackages( + IEnumerable pkgs, + List pathsToSearch) + { + foreach (var pkg in pkgs) + { + // Filter on specific version. + var nugetVersion = new NuGetVersion(pkg.Version); + var pkgVersionRange = new VersionRange( + minVersion: nugetVersion, + includeMinVersion: true, + maxVersion: nugetVersion, + includeMaxVersion: true); + + // Search by package name. + var foundPkgPaths = FilterPkgPathsByName( + names: new string[] { pkg.Name }, + pathsToSearch); + + // Filter by package version. + foreach (var pkgPath in FilterPkgPathsByVersion( + versionRange: pkgVersionRange, + dirsToSearch: foundPkgPaths, + selectPrereleaseOnly: false)) + { + PSResourceInfo returnPkg = OutputPackageObject(pkgPath, _scriptDictionary); + if (returnPkg != null) + { + yield return returnPkg; + } + } + } + } + public IEnumerable GetPackagesFromPath( string[] name, VersionRange versionRange, diff --git a/src/code/InstallHelper.cs b/src/code/InstallHelper.cs index 829732c44..0db980ddb 100644 --- a/src/code/InstallHelper.cs +++ b/src/code/InstallHelper.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using Microsoft.PowerShell.Commands; using Microsoft.PowerShell.PowerShellGet.UtilClasses; using MoreLinq.Extensions; using NuGet.Common; @@ -15,7 +14,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Globalization; using System.IO; using System.Linq; @@ -271,22 +269,12 @@ private List FilterByInstalledPkgs(List packages // ./InstallPackagePath2/PackageC // ./InstallPackagePath3/PackageD - // Get package names - var packageNames = new HashSet(StringComparer.CurrentCultureIgnoreCase); - foreach (var pkg in packages) - { - packageNames.Add(pkg.Name); - } - // 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. var getHelper = new GetHelper(_cmdletPassedIn); var installedPackageNames = new HashSet(StringComparer.CurrentCultureIgnoreCase); - foreach (var installedPkg in getHelper.GetPackagesFromPath( - name: packageNames.ToArray(), - versionRange: _versionRange, - pathsToSearch: _pathsToSearch, - selectPrereleaseOnly: false)) + foreach (var installedPkg in getHelper.GetInstalledPackages( + pkgs: packages, + pathsToSearch: _pathsToSearch)) { installedPackageNames.Add(installedPkg.Name); } @@ -307,7 +295,12 @@ private List FilterByInstalledPkgs(List packages } else { - // Remove from list package versions that are already installed. + // Remove from tracking list of packages to install. + _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)); + _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); } } @@ -315,8 +308,11 @@ private List FilterByInstalledPkgs(List packages return filteredPackages; } + /// + /// Install provided list of packages, which include Dependent packages if requested. + /// private List InstallPackage( - IEnumerable pkgsToInstall, // those found to be required to be installed (includes Dependency packages as well) + List pkgsToInstall, string repoName, string repoUri, PSCredentialInfo repoCredentialInfo, @@ -324,13 +320,13 @@ private List InstallPackage( bool isLocalRepo) { List pkgsSuccessfullyInstalled = new List(); - int totalPkgs = pkgsToInstall.Count(); + int totalPkgs = pkgsToInstall.Count; // Counters for tracking current package out of total - int totalInstalledPkgCount = 0; + int currentInstalledPkgCount = 0; foreach (PSResourceInfo pkg in pkgsToInstall) { - totalInstalledPkgCount++; + currentInstalledPkgCount++; var tempInstallPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try { @@ -348,7 +344,7 @@ private List InstallPackage( if (!_quiet) { int activityId = 0; - int percentComplete = ((totalInstalledPkgCount * 100) / totalPkgs); + int percentComplete = ((currentInstalledPkgCount * 100) / totalPkgs); string activity = string.Format("Installing {0}...", pkg.Name); string statusDescription = string.Format("{0}% Complete", percentComplete); _cmdletPassedIn.WriteProgress( diff --git a/test/FindPSResource.Tests.ps1 b/test/FindPSResource.Tests.ps1 index 9d946b33b..53449b2d9 100644 --- a/test/FindPSResource.Tests.ps1 +++ b/test/FindPSResource.Tests.ps1 @@ -122,7 +122,7 @@ Describe 'Test Find-PSResource for Module' { ) { param($Version, $Description) - $res = Find-PSResource -Name $testModuleName -Version $Version -Repository $PSGalleryName + $res = Find-PSResource -Name $testModuleName -Version $Version -Repository $PSGalleryName 2>$null $res | Should -BeNullOrEmpty } diff --git a/test/UpdatePSResource.Tests.ps1 b/test/UpdatePSResource.Tests.ps1 index 0bbbdc2da..901a5a0bc 100644 --- a/test/UpdatePSResource.Tests.ps1 +++ b/test/UpdatePSResource.Tests.ps1 @@ -123,7 +123,7 @@ Describe 'Test Update-PSResource' { param($Version, $Description) Install-PSResource -Name $testModuleName -Version "1.0.0.0" -Repository $PSGalleryName -TrustRepository - Update-PSResource -Name $testModuleName -Version $Version -Repository $PSGalleryName -TrustRepository + Update-PSResource -Name $testModuleName -Version $Version -Repository $PSGalleryName -TrustRepository 2>$null $res = Get-PSResource -Name $testModuleName $isPkgUpdated = $false From 8cae05c02d48f3ff906e9761ac37aa6ba508cb2b Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Fri, 22 Jul 2022 09:42:45 -0700 Subject: [PATCH 4/7] Fix logic error --- src/code/PublishPSResource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index 7b3eee131..9edccca59 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -895,7 +895,7 @@ private bool CheckDependenciesExist(Hashtable dependencies, string repositoryNam credential: Credential, includeDependencies: false); - if (foundDependencies.Count > 0) + if (foundDependencies.Count is 0) { var message = String.Format("Dependency '{0}' was not found in repository '{1}'. Make sure the dependency is published to the repository before publishing this module.", dependency, repositoryName); var ex = new ArgumentException(message); From 5ecea561c851195ad395e2a567775e5bb0dc11ad Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Fri, 22 Jul 2022 09:47:16 -0700 Subject: [PATCH 5/7] Style change --- src/code/PublishPSResource.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/code/PublishPSResource.cs b/src/code/PublishPSResource.cs index 9edccca59..2854da350 100644 --- a/src/code/PublishPSResource.cs +++ b/src/code/PublishPSResource.cs @@ -236,7 +236,6 @@ protected override void EndProcessing() try { Utils.ValidateModuleManifest(resourceFilePath, out errorMsgs); - } finally { if (errorMsgs.Length > 0) From 91051c9946d8b907fc1fdf295be8b2c912748bcb Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Fri, 22 Jul 2022 11:15:59 -0700 Subject: [PATCH 6/7] Minor clean up --- src/code/FindHelper.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/code/FindHelper.cs b/src/code/FindHelper.cs index 3c3d8abdb..97457d74d 100644 --- a/src/code/FindHelper.cs +++ b/src/code/FindHelper.cs @@ -629,8 +629,8 @@ SourceCacheContext sourceCacheContext if (dep.VersionRange == VersionRange.All) { - // return latest version - IPackageSearchMetadata depPkgLatestVersion = depPkgs.First(); + // Return latest version, which is first in the list. + IPackageSearchMetadata depPkgLatestVersion = depPkgs[0]; if (!PSResourceInfo.TryConvert( metadataToParse: depPkgLatestVersion, @@ -656,9 +656,9 @@ SourceCacheContext sourceCacheContext p.Identity.Version, VersionComparer.VersionRelease)).OrderByDescending( p => p.Identity.Version).ToList(); - if (pkgVersionsInRange.Count() > 0) + if (pkgVersionsInRange.Count > 0) { - IPackageSearchMetadata depPkgLatestInRange = pkgVersionsInRange.First(); + IPackageSearchMetadata depPkgLatestInRange = pkgVersionsInRange[0]; if (depPkgLatestInRange != null) { if (!PSResourceInfo.TryConvert( From 186e88f2c5490735645f5fecb9bf4bbf136086a6 Mon Sep 17 00:00:00 2001 From: PaulHigin Date: Tue, 26 Jul 2022 14:29:24 -0700 Subject: [PATCH 7/7] Use count property --- src/code/InstallHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/InstallHelper.cs b/src/code/InstallHelper.cs index 0db980ddb..515cdd762 100644 --- a/src/code/InstallHelper.cs +++ b/src/code/InstallHelper.cs @@ -222,7 +222,7 @@ private List ProcessRepositories( pkgsFromRepoToInstall = FilterByInstalledPkgs(pkgsFromRepoToInstall); } - if (!pkgsFromRepoToInstall.Any()) + if (pkgsFromRepoToInstall.Count is 0) { continue; }