Skip to content

get FindTag (multiple), FindType, FindCommandName, FindDSCResourceNam… #857

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 4 additions & 66 deletions src/code/FindHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -132,68 +131,6 @@ public List<PSResourceInfo> 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));
Expand Down Expand Up @@ -230,7 +167,7 @@ private IEnumerable<PSResourceInfo> 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;
}
Expand All @@ -242,6 +179,7 @@ private IEnumerable<PSResourceInfo> HttpSearchFromRepository(PSRepositoryInfo re
yield return pkg;
}
}

yield break;
}

Expand Down Expand Up @@ -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
}

Expand Down
52 changes: 33 additions & 19 deletions src/code/HttpFindPSResource.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;
using System.Collections;
using System.Linq;
using System.Xml;
using Microsoft.PowerShell.PowerShellGet.UtilClasses;
Expand Down Expand Up @@ -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
/// </summary>
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<PSResourceInfo> pkgsFound = new List<PSResourceInfo>();
HashSet<string> tagPkgs = new HashSet<string>();

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();
Expand Down
2 changes: 1 addition & 1 deletion src/code/IFindPSResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
/// </summary>
PSResourceInfo[] FindTags(string[] tags, PSRepositoryInfo repository, bool includePrerelease, out string errRecord);
PSResourceInfo[] FindTags(string[] tags, PSRepositoryInfo repository, bool includePrerelease, ResourceType type, out string errRecord);

/// <summary>
/// Find method which allows for searching for packages with resource type specified from a repository and returns latest version for each.
Expand Down
4 changes: 2 additions & 2 deletions src/code/IServerAPICalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ public interface IServerAPICalls


/// <summary>
/// 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
/// </summary>
string FindTags(string[] tags, PSRepositoryInfo repository, bool includePrerelease, out string errRecord);
string[] FindTag(string tag, PSRepositoryInfo repository, bool includePrerelease, ResourceType _type, out string errRecord);


/// <summary>
Expand Down
11 changes: 5 additions & 6 deletions src/code/PSResourceInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
51 changes: 44 additions & 7 deletions src/code/V2ServerAPICalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using Microsoft.PowerShell.PowerShellGet.UtilClasses;
using System;
using System.Collections.Generic;
using System.Net.Http;
using NuGet.Versioning;

Expand Down Expand Up @@ -66,21 +67,57 @@ public string FindAllWithPrerelease(PSRepositoryInfo repository, out string errR


/// <summary>
/// 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
/// </summary>
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<string> responses = new List<string>();

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


Expand Down