Skip to content

Tag type paramset #478

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 13 commits into from
Sep 29, 2021
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
4 changes: 2 additions & 2 deletions help/Find-PSResource.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ Accept wildcard characters: False
```

### -Repository
Specifies one or more repository names to search.
Specifies one or more repository names to search, which can include wildcard.
If not specified, search will include all currently registered repositories, in order of highest priority, until a repository is found that contains the package.

```yaml
Expand All @@ -212,7 +212,7 @@ Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
Accept wildcard characters: True
```

### -Tag
Expand Down
2 changes: 2 additions & 0 deletions src/PSGet.Format.ps1xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<TableColumnHeader><Label>Name</Label></TableColumnHeader>
<TableColumnHeader><Label>Version</Label></TableColumnHeader>
<TableColumnHeader><Label>Prerelease</Label></TableColumnHeader>
<TableColumnHeader><Label>Repository</Label></TableColumnHeader>
<TableColumnHeader><Label>Description</Label></TableColumnHeader>
</TableHeaders>
<TableRowEntries>
Expand All @@ -19,6 +20,7 @@
<TableColumnItem><PropertyName>Name</PropertyName></TableColumnItem>
<TableColumnItem><PropertyName>Version</PropertyName></TableColumnItem>
<TableColumnItem><PropertyName>PrereleaseLabel</PropertyName></TableColumnItem>
<TableColumnItem><PropertyName>Repository</PropertyName></TableColumnItem>
<TableColumnItem><PropertyName>Description</PropertyName></TableColumnItem>
</TableColumnItems>
</TableRowEntry>
Expand Down
93 changes: 75 additions & 18 deletions src/code/FindHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ internal class FindHelper
private SwitchParameter _includeDependencies = false;
private readonly string _psGalleryRepoName = "PSGallery";
private readonly string _psGalleryScriptsRepoName = "PSGalleryScripts";
private readonly string _psGalleryURL = "https://www.powershellgallery.com/api/v2";
private readonly string _poshTestGalleryRepoName = "PoshTestGallery";
private readonly string _poshTestGalleryScriptsRepoName = "PoshTestGalleryScripts";
private readonly string _poshTestGalleryURL = "https://www.poshtestgallery.com/api/v2";
private bool _isADOFeedRepository;
private bool _repositoryNameContainsWildcard;

// NuGet's SearchAsync() API takes a top parameter of 6000, but testing shows for PSGallery
// usually a max of around 5990 is returned while more are left to retrieve in a second SearchAsync() call
Expand Down Expand Up @@ -74,10 +79,23 @@ public IEnumerable<PSResourceInfo> FindByResourceName(

List<PSRepositoryInfo> repositoriesToSearch;

//determine if repository array of names of repositories input to be searched contains wildcard
if (repository != null)
{
repository = Utils.ProcessNameWildcards(repository, out string[] errorMsgs, out _repositoryNameContainsWildcard);
foreach (string error in errorMsgs)
{
_cmdletPassedIn.WriteError(new ErrorRecord(
new PSInvalidOperationException(error),
"ErrorFilteringNamesForUnsupportedWildcards",
ErrorCategory.InvalidArgument,
this));
}
}

try
{
repositoriesToSearch = RepositorySettings.Read(repository, out string[] errorList);

foreach (string error in errorList)
{
_cmdletPassedIn.WriteError(new ErrorRecord(
Expand All @@ -97,12 +115,14 @@ public IEnumerable<PSResourceInfo> FindByResourceName(
yield break;
}

// loop through repositoriesToSearch and if PSGallery add it 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++)
{
if (String.Equals(repositoriesToSearch[i].Name, _psGalleryRepoName, StringComparison.InvariantCultureIgnoreCase))
if (String.Equals(repositoriesToSearch[i].Url.AbsoluteUri, _psGalleryURL, StringComparison.InvariantCultureIgnoreCase))
{
// for PowerShellGallery, Module and Script resources have different endpoints so separate repositories have to be registered
// 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
Expand All @@ -115,11 +135,32 @@ public IEnumerable<PSResourceInfo> FindByResourceName(
}
else if (_type != ResourceType.None && _type == ResourceType.Script)
{
_cmdletPassedIn.WriteVerbose("Type Script provided, so add PSGalleryScripts and remove PSGallery (Modules only)");
_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].Url.AbsoluteUri, _poshTestGalleryURL, 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 poshTestGalleryScriptsUrl = new Uri("https://www.poshtestgallery.com/api/v2/items/psscript/");
PSRepositoryInfo poshTestGalleryScripts = new PSRepositoryInfo(_poshTestGalleryScriptsRepoName, poshTestGalleryScriptsUrl, repositoriesToSearch[i].Priority, false);
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++)
Expand Down Expand Up @@ -203,7 +244,8 @@ public IEnumerable<PSResourceInfo> SearchFromRepository(
context = new SourceCacheContext();

foreach(PSResourceInfo pkg in SearchAcrossNamesInRepository(
repositoryName: repositoryName,
repositoryName: String.Equals(repositoryUrl.AbsoluteUri, _psGalleryURL, StringComparison.InvariantCultureIgnoreCase) ? _psGalleryRepoName :
(String.Equals(repositoryUrl.AbsoluteUri, _poshTestGalleryURL, StringComparison.InvariantCultureIgnoreCase) ? _poshTestGalleryRepoName : repositoryName),
pkgSearchResource: resourceSearch,
pkgMetadataResource: resourceMetadata,
searchFilter: filter,
Expand Down Expand Up @@ -309,7 +351,13 @@ private IEnumerable<PSResourceInfo> FindFromPackageSourceSearchAPI(
}

foundPackagesMetadata.AddRange(retrievedPkgs.ToList());
_pkgsLeftToFind.Remove(pkgName);

// _pkgsLeftToFind.Remove(pkgName);

if (!_repositoryNameContainsWildcard)
{
_pkgsLeftToFind.Remove(pkgName);
}
}
else
{
Expand All @@ -326,7 +374,6 @@ private IEnumerable<PSResourceInfo> FindFromPackageSourceSearchAPI(
IEnumerable<IPackageSearchMetadata> wildcardPkgs = null;
try
{
_cmdletPassedIn.WriteVerbose("searching with name: " + pkgName);
// SearchAsync() API returns the latest version only for all packages that match the wild-card name
wildcardPkgs = pkgSearchResource.SearchAsync(
searchTerm: pkgName,
Expand Down Expand Up @@ -369,18 +416,28 @@ private IEnumerable<PSResourceInfo> FindFromPackageSourceSearchAPI(
foundPackagesMetadata.AddRange(wildcardPkgs.Where(
p => nameWildcardPattern.IsMatch(p.Identity.Id)).ToList());

// 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)
// PSGallery + Type == C -> M
// PSGallery + Type == D -> M

bool needToCheckPSGalleryScriptsRepo = String.Equals(repositoryName, _psGalleryRepoName, StringComparison.InvariantCultureIgnoreCase) && _type == ResourceType.None;
if (foundPackagesMetadata.Any() && !needToCheckPSGalleryScriptsRepo)
if (!_repositoryNameContainsWildcard)
{
_pkgsLeftToFind.Remove(pkgName);
// 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)
// PSGallery + Type == C -> M
// PSGallery + Type == D -> M

if (String.Equals(repositoryName, _psGalleryRepoName, StringComparison.InvariantCultureIgnoreCase) ||
String.Equals(repositoryName, _poshTestGalleryRepoName, StringComparison.InvariantCultureIgnoreCase))
{
if (foundPackagesMetadata.Any() && _type != ResourceType.None)
{
_pkgsLeftToFind.Remove(pkgName);
}
}

}

// if repository names did contain wildcard, we want to do an exhaustive search across all the repositories
// which matched the input repository name search term.
}

if (foundPackagesMetadata.Count == 0)
Expand Down
38 changes: 11 additions & 27 deletions src/code/FindPSResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,26 +176,21 @@ private void ProcessResourceNameParameterSet()
{
if (!MyInvocation.BoundParameters.ContainsKey(nameof(Name)))
{
// TODO: Add support for Tag and Type parameters without Name parameter being specified.
if (MyInvocation.BoundParameters.ContainsKey(nameof(Type)) || MyInvocation.BoundParameters.ContainsKey(nameof(Tag)))
// only cases where Name is allowed to not be specified is if Type or Tag parameters are
if (!MyInvocation.BoundParameters.ContainsKey(nameof(Type)) && !MyInvocation.BoundParameters.ContainsKey(nameof(Tag)))
{
ThrowTerminatingError(
new ErrorRecord(
new PSNotImplementedException("Search by Tag or Type parameter is not yet implemented."),
"TagTypeSearchNotYetImplemented",
ErrorCategory.NotImplemented,
new PSInvalidOperationException("Name parameter must be provided."),
"NameParameterNotProvided",
ErrorCategory.InvalidOperation,
this));
}

ThrowTerminatingError(
new ErrorRecord(
new PSInvalidOperationException("Name parameter must be provided."),
"NameParameterNotProvided",
ErrorCategory.InvalidOperation,
this));
Name = new string[] {"*"};
}
var namesToSearch = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard);

Name = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard);

foreach (string error in errorMsgs)
{
Expand All @@ -208,21 +203,10 @@ private void ProcessResourceNameParameterSet()

// this catches the case where Name wasn't passed in as null or empty,
// but after filtering out unsupported wildcard names there are no elements left in namesToSearch
if (namesToSearch.Length == 0)
{
return;
}

if (String.Equals(namesToSearch[0], "*", StringComparison.InvariantCultureIgnoreCase))
if (Name.Length == 0)
{
// WriteVerbose("Package names were detected to be (or contain an element equal to): '*', so all packages will be updated");
WriteError(new ErrorRecord(
new PSInvalidOperationException("-Name '*' is not supported for Find-PSResource so all Name entries will be discarded."),
"NameEqualsWildcardIsNotSupported",
ErrorCategory.InvalidArgument,
this));
return;
}
}

FindHelper findHelper = new FindHelper(_cancellationToken, this);
List<PSResourceInfo> foundPackages = new List<PSResourceInfo>();
Expand All @@ -241,7 +225,7 @@ private void ProcessResourceNameParameterSet()
}

foreach (var uniquePackageVersion in foundPackages.GroupBy(
m => new {m.Name, m.Version}).Select(
m => new {m.Name, m.Version, m.Repository}).Select(
group => group.First()).ToList())
{
WriteObject(uniquePackageVersion);
Expand Down
Loading