From 733c225559d816aad235f39ed45524c4ebc73cec Mon Sep 17 00:00:00 2001 From: Anam Navied Date: Thu, 10 Nov 2022 17:32:33 -0500 Subject: [PATCH] get FindTag (multiple), FindType, FindCommandName, FindDSCResourceName to work --- src/code/FindHelper.cs | 70 ++-------------------------------- src/code/HttpFindPSResource.cs | 52 ++++++++++++++++--------- src/code/IFindPSResource.cs | 2 +- src/code/IServerAPICalls.cs | 4 +- src/code/PSResourceInfo.cs | 11 +++--- src/code/V2ServerAPICalls.cs | 51 +++++++++++++++++++++---- 6 files changed, 89 insertions(+), 101 deletions(-) diff --git a/src/code/FindHelper.cs b/src/code/FindHelper.cs index 3119a3165..5ef2995fe 100644 --- a/src/code/FindHelper.cs +++ b/src/code/FindHelper.cs @@ -39,7 +39,6 @@ internal class FindHelper private readonly string _psGalleryScriptsRepoName = "PSGalleryScripts"; private readonly string _psGalleryUri = "https://www.powershellgallery.com/api/v2"; private readonly string _poshTestGalleryRepoName = "PoshTestGallery"; - private readonly string _poshTestGalleryScriptsRepoName = "PoshTestGalleryScripts"; private readonly string _poshTestGalleryUri = "https://www.poshtestgallery.com/api/v2"; private bool _isADOFeedRepository; private bool _repositoryNameContainsWildcard; @@ -132,68 +131,6 @@ public List FindByResourceName( return foundPackages; } - // 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++) - { - if (String.Equals(repositoriesToSearch[i].Uri.AbsoluteUri, _psGalleryUri, StringComparison.InvariantCultureIgnoreCase)) - { - // special case: for PowerShellGallery, Module and Script resources have different endpoints so separate repositories have to be registered - // with those endpoints in order for the NuGet APIs to search across both in the case where name includes '*' - - // detect if Script repository needs to be added and/or Module repository needs to be skipped - Uri psGalleryScriptsUri = new Uri("http://www.powershellgallery.com/api/v2/items/psscript/"); - PSRepositoryInfo psGalleryScripts = new PSRepositoryInfo( - _psGalleryScriptsRepoName, - psGalleryScriptsUri, - repositoriesToSearch[i].Priority, - trusted: false, - credentialInfo: null, - repositoriesToSearch[i].ApiVersion); - - if (_type == ResourceType.None) - { - _cmdletPassedIn.WriteVerbose("Null Type provided, so add PSGalleryScripts repository"); - repositoriesToSearch.Insert(i + 1, psGalleryScripts); - } - else if (_type != ResourceType.None && _type == ResourceType.Script) - { - _cmdletPassedIn.WriteVerbose("Type Script provided, so add PSGalleryScripts and remove PSGallery (Modules only) from search consideration"); - repositoriesToSearch.Insert(i + 1, psGalleryScripts); - repositoriesToSearch.RemoveAt(i); // remove PSGallery - } - } - else if (String.Equals(repositoriesToSearch[i].Uri.AbsoluteUri, _poshTestGalleryUri, StringComparison.InvariantCultureIgnoreCase)) - { - // special case: for PoshTestGallery, Module and Script resources have different endpoints so separate repositories have to be registered - // with those endpoints in order for the NuGet APIs to search across both in the case where name includes '*' - - // detect if Script repository needs to be added and/or Module repository needs to be skipped - Uri poshTestGalleryScriptsUri = new Uri("https://www.poshtestgallery.com/api/v2/items/psscript/"); - PSRepositoryInfo poshTestGalleryScripts = new PSRepositoryInfo( - _poshTestGalleryScriptsRepoName, - poshTestGalleryScriptsUri, - repositoriesToSearch[i].Priority, - trusted: false, - credentialInfo: null, - repositoriesToSearch[i].ApiVersion); - - if (_type == ResourceType.None) - { - _cmdletPassedIn.WriteVerbose("Null Type provided, so add PoshTestGalleryScripts repository"); - repositoriesToSearch.Insert(i + 1, poshTestGalleryScripts); - } - else if (_type != ResourceType.None && _type == ResourceType.Script) - { - _cmdletPassedIn.WriteVerbose("Type Script provided, so add PoshTestGalleryScripts and remove PoshTestGallery (Modules only) from search consideration"); - repositoriesToSearch.Insert(i + 1, poshTestGalleryScripts); - repositoriesToSearch.RemoveAt(i); // remove PoshTestGallery - } - } - - } - for (int i = 0; i < repositoriesToSearch.Count && _pkgsLeftToFind.Any(); i++) { _cmdletPassedIn.WriteVerbose(string.Format("Searching in repository {0}", repositoriesToSearch[i].Name)); @@ -230,7 +167,7 @@ private IEnumerable HttpSearchFromRepository(PSRepositoryInfo re if (_tag != null) { // TODO: this is currently very buggy and the url queries need to be fixed - foreach (PSResourceInfo pkgs in HttpFindTags(repositoryInfo)) + foreach (PSResourceInfo pkgs in HttpFindTags(repositoryInfo, _type)) { yield return pkgs; } @@ -242,6 +179,7 @@ private IEnumerable HttpSearchFromRepository(PSRepositoryInfo re yield return pkg; } } + yield break; } @@ -757,9 +695,9 @@ private bool IsTagMatch(PSResourceInfo pkg) return _tag.Intersect(pkg.Tags, StringComparer.InvariantCultureIgnoreCase).ToList().Count > 0; } - private PSResourceInfo[] HttpFindTags(PSRepositoryInfo repository) + private PSResourceInfo[] HttpFindTags(PSRepositoryInfo repository, ResourceType type) { - return _httpFindPSResource.FindTags(_tag, repository, _prerelease, out string errRecord); + return _httpFindPSResource.FindTags(_tag, repository, _prerelease, type, out string errRecord); // TODO: write out error } diff --git a/src/code/HttpFindPSResource.cs b/src/code/HttpFindPSResource.cs index 1ca2dee1f..4e6a66e55 100644 --- a/src/code/HttpFindPSResource.cs +++ b/src/code/HttpFindPSResource.cs @@ -1,3 +1,5 @@ +using System; +using System.Collections; using System.Linq; using System.Xml; using Microsoft.PowerShell.PowerShellGet.UtilClasses; @@ -56,31 +58,43 @@ public PSResourceInfo FindAll(PSRepositoryInfo repository, bool includePrereleas /// - No prerelease: http://www.powershellgallery.com/api/v2/Search()?$filter=IsLatestVersion&searchTerm='tag:JSON' /// - Include prerelease: http://www.powershellgallery.com/api/v2/Search()?$filter=IsAbsoluteLatestVersion&searchTerm='tag:JSON'&includePrerelease=true /// - public PSResourceInfo[] FindTags(string[] tags, PSRepositoryInfo repository, bool includePrerelease, out string errRecord) + public PSResourceInfo[] FindTags(string[] tags, PSRepositoryInfo repository, bool includePrerelease, ResourceType type, out string errRecord) { - var response = v2ServerAPICall.FindTags(tags, repository, includePrerelease, out errRecord); - - var elemList = ConvertResponseToXML(response); + errRecord = String.Empty; List pkgsFound = new List(); + HashSet tagPkgs = new HashSet(); - foreach (var element in elemList) + foreach (string tag in tags) { - PSResourceInfo.TryConvertFromXml( - element, - includePrerelease, - out PSResourceInfo psGetInfo, - repository.Name, - out string errorMsg); + string[] responses = v2ServerAPICall.FindTag(tag, repository, includePrerelease, type, out errRecord); - if (psGetInfo != null) + foreach (string response in responses) { - pkgsFound.Add(psGetInfo); - } - else - { - // TODO: Write error for corresponding null scenario - errRecord = errorMsg; - } + var elemList = ConvertResponseToXML(response); + + foreach (var element in elemList) + { + PSResourceInfo.TryConvertFromXml( + element, + includePrerelease, + out PSResourceInfo psGetInfo, + repository.Name, + out string errorMsg); + + if (psGetInfo != null && !tagPkgs.Contains(psGetInfo.Name)) + { + tagPkgs.Add(psGetInfo.Name); + pkgsFound.Add(psGetInfo); + } + else + { + // TODO: Write error for corresponding null scenario + // TODO: array out of bounds exception when name does not exist + // http://www.powershellgallery.com/api/v2/Search()?$filter=IsLatestVersion&searchTerm='tag:PSCommand_Get-TargetResource' + errRecord = errorMsg; + } + } + } } return pkgsFound.ToArray(); diff --git a/src/code/IFindPSResource.cs b/src/code/IFindPSResource.cs index 71da7c163..4594d2956 100644 --- a/src/code/IFindPSResource.cs +++ b/src/code/IFindPSResource.cs @@ -21,7 +21,7 @@ public interface IFindPSResource /// - No prerelease: http://www.powershellgallery.com/api/v2/Search()?$filter=IsLatestVersion&searchTerm='tag:JSON' /// - Include prerelease: http://www.powershellgallery.com/api/v2/Search()?$filter=IsAbsoluteLatestVersion&searchTerm='tag:JSON'&includePrerelease=true /// - PSResourceInfo[] FindTags(string[] tags, PSRepositoryInfo repository, bool includePrerelease, out string errRecord); + PSResourceInfo[] FindTags(string[] tags, PSRepositoryInfo repository, bool includePrerelease, ResourceType type, out string errRecord); /// /// Find method which allows for searching for packages with resource type specified from a repository and returns latest version for each. diff --git a/src/code/IServerAPICalls.cs b/src/code/IServerAPICalls.cs index 62adc0955..404bcdd23 100644 --- a/src/code/IServerAPICalls.cs +++ b/src/code/IServerAPICalls.cs @@ -27,12 +27,12 @@ public interface IServerAPICalls /// - /// Find method which allows for searching for packages with tag(s) from a repository and returns latest version for each. + /// Find method which allows for searching for packages with tag from a repository and returns latest version for each. /// Examples: Search -Tag "JSON" -Repository PSGallery /// API call: /// - Include prerelease: http://www.powershellgallery.com/api/v2/Search()?$filter=IsAbsoluteLatestVersion&searchTerm='tag:JSON'&includePrerelease=true /// - string FindTags(string[] tags, PSRepositoryInfo repository, bool includePrerelease, out string errRecord); + string[] FindTag(string tag, PSRepositoryInfo repository, bool includePrerelease, ResourceType _type, out string errRecord); /// diff --git a/src/code/PSResourceInfo.cs b/src/code/PSResourceInfo.cs index 18c13d915..55a9fbebb 100644 --- a/src/code/PSResourceInfo.cs +++ b/src/code/PSResourceInfo.cs @@ -18,14 +18,13 @@ namespace Microsoft.PowerShell.PowerShellGet.UtilClasses { #region Enums - [Flags] public enum ResourceType { - None = 0x0, - Module = 0x1, - Script = 0x2, - Command = 0x4, - DscResource = 0x8 + None, + Module, + Script, + Command, + DscResource } public enum VersionType diff --git a/src/code/V2ServerAPICalls.cs b/src/code/V2ServerAPICalls.cs index 75d6abd72..f2d8a5cb4 100644 --- a/src/code/V2ServerAPICalls.cs +++ b/src/code/V2ServerAPICalls.cs @@ -3,6 +3,7 @@ using Microsoft.PowerShell.PowerShellGet.UtilClasses; using System; +using System.Collections.Generic; using System.Net.Http; using NuGet.Versioning; @@ -66,21 +67,57 @@ public string FindAllWithPrerelease(PSRepositoryInfo repository, out string errR /// - /// Find method which allows for searching for packages with tag(s) from a repository and returns latest version for each. + /// Find method which allows for searching for packages with tag from a repository and returns latest version for each. /// Examples: Search -Tag "JSON" -Repository PSGallery /// API call: /// - Include prerelease: http://www.powershellgallery.com/api/v2/Search()?$filter=IsAbsoluteLatestVersion&searchTerm=tag:JSON&includePrerelease=true /// - public string FindTags(string[] tags, PSRepositoryInfo repository, bool includePrerelease, out string errRecord) + public string[] FindTag(string tag, PSRepositoryInfo repository, bool includePrerelease, ResourceType type, out string errRecord) { - var tagsString = String.Join(" ", tags); + // scenarios with type + tags: + // type: None -> search both endpoints + // type: M -> just search Module endpoint + // type: S -> just search Scripts end point + // type: DSCResource -> just search Modules + // type: Command -> just search Modules + errRecord = String.Empty; var prereleaseFilter = includePrerelease ? "&includePrerelease=true" : string.Empty; + List responses = new List(); - // There are no quotations around tag(s) in the url because this should be an "or" operation - var requestUrlV2 = $"{repository.Uri}/Search()?$filter=IsAbsoluteLatestVersion&searchTerm='tag:{tagsString}'{prereleaseFilter}&{select}"; + if (type == ResourceType.Script || type == ResourceType.None) + { + // $"{repository.Uri}/items/psscript/Search()?$filter=IsAbsoluteLatestVersion&searchTerm='tag:{tag}+tag:PSScript'{prereleaseFilter}&{select}"; + var scriptsRequestUrlV2 = $"{repository.Uri}/items/psscript/Search()?$filter=IsAbsoluteLatestVersion&searchTerm='tag:{tag}'{prereleaseFilter}&{select}"; + responses.Add(HttpRequestCall(requestUrlV2: scriptsRequestUrlV2, out string scriptErrorRecord)); + // TODO: add error handling here + } + + if (type != ResourceType.Script) + { + if (type == ResourceType.None || type == ResourceType.Module) + { + // type: Module or Command or DSCResource or None + var modulesRequestUrlV2 = $"{repository.Uri}/Search()?$filter=IsAbsoluteLatestVersion&searchTerm='tag:{tag}'{prereleaseFilter}&{select}"; + responses.Add(HttpRequestCall(requestUrlV2: modulesRequestUrlV2, out string moduleErrorRecord)); + } + else if (type == ResourceType.Command) + { + // http://www.powershellgallery.com/api/v2/Search()?$filter=IsLatestVersion&searchTerm='tag:PSCommand_Get-TargetResource' + var commandRequestUrlV2 = $"{repository.Uri}/Search()?$filter=IsAbsoluteLatestVersion&searchTerm='tag:PSCommand_{tag}'{prereleaseFilter}&{select}"; + responses.Add(HttpRequestCall(requestUrlV2: commandRequestUrlV2, out string commandErrorRecord)); + } + else + { + // DSCResource type + var dscResourceRequestUrlV2 = $"{repository.Uri}/Search()?$filter=IsAbsoluteLatestVersion&searchTerm='tag:PSDscResource_{tag}'{prereleaseFilter}&{select}"; + responses.Add(HttpRequestCall(requestUrlV2: dscResourceRequestUrlV2, out string dscResourceErrorRecord)); + } - Console.WriteLine(requestUrlV2); - return HttpRequestCall(requestUrlV2, out errRecord); + // TODO: add error handling here + + } + + return responses.ToArray(); }