Skip to content

Commit f4167e5

Browse files
authored
Tag name (#995)
1 parent a9264d0 commit f4167e5

11 files changed

+703
-165
lines changed

src/code/FindHelper.cs

+123-114
Large diffs are not rendered by default.

src/code/FindPSResource.cs

+54-14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using Microsoft.PowerShell.PowerShellGet.UtilClasses;
5+
using NuGet.Versioning;
56
using System;
67
using System.Collections.Generic;
78
using System.Linq;
@@ -30,7 +31,6 @@ public sealed class FindPSResource : PSCmdlet
3031
private const string NameParameterSet = "NameParameterSet";
3132
private const string CommandNameParameterSet = "CommandNameParameterSet";
3233
private const string DscResourceNameParameterSet = "DscResourceNameParameterSet";
33-
private const string TagParameterSet = "TagParameterSet";
3434
private CancellationTokenSource _cancellationTokenSource;
3535
private FindHelper _findHelper;
3636

@@ -50,10 +50,9 @@ public sealed class FindPSResource : PSCmdlet
5050

5151
/// <summary>
5252
/// Specifies one or more resource types to find.
53-
/// Resource types supported are: Module, Script, Command, DscResource
53+
/// Resource types supported are: Module, Script
5454
/// </summary>
5555
[Parameter(ParameterSetName = NameParameterSet)]
56-
[Parameter(ParameterSetName = TagParameterSet)]
5756
public ResourceType Type { get; set; }
5857

5958
/// <summary>
@@ -86,7 +85,7 @@ public sealed class FindPSResource : PSCmdlet
8685
/// <summary>
8786
/// Filters search results for resources that include one or more of the specified tags.
8887
/// </summary>
89-
[Parameter(ParameterSetName = TagParameterSet)]
88+
[Parameter(ParameterSetName = NameParameterSet)]
9089
[ValidateNotNull]
9190
public string[] Tag { get; set; }
9291

@@ -157,10 +156,6 @@ protected override void ProcessRecord()
157156
ProcessCommandOrDscParameterSet(isSearchingForCommands: false);
158157
break;
159158

160-
case TagParameterSet:
161-
ProcessTagParameterSet();
162-
break;
163-
164159
default:
165160
Dbg.Assert(false, "Invalid parameter set");
166161
break;
@@ -173,20 +168,28 @@ protected override void ProcessRecord()
173168

174169
private void ProcessResourceNameParameterSet()
175170
{
171+
// only cases where Name is allowed to not be specified is if Type or Tag parameters are
176172
if (!MyInvocation.BoundParameters.ContainsKey(nameof(Name)))
177173
{
178-
// only cases where Name is allowed to not be specified is if Type or Tag parameters are
179-
if (!MyInvocation.BoundParameters.ContainsKey(nameof(Type)) && !MyInvocation.BoundParameters.ContainsKey(nameof(Tag)))
174+
if (MyInvocation.BoundParameters.ContainsKey(nameof(Tag)))
175+
{
176+
// case where Name specified: false, Tag specified: true (i.e just search by Tags)
177+
ProcessTagParameterSet(); // TODO: rename
178+
return;
179+
}
180+
else if (MyInvocation.BoundParameters.ContainsKey(nameof(Type)))
181+
{
182+
Name = new string[] {"*"};
183+
}
184+
else
180185
{
181186
ThrowTerminatingError(
182187
new ErrorRecord(
183-
new PSInvalidOperationException("Name parameter must be provided."),
188+
new PSInvalidOperationException("Name parameter must be provided, unless Tag or Type parameters are used."),
184189
"NameParameterNotProvided",
185190
ErrorCategory.InvalidOperation,
186191
this));
187192
}
188-
189-
Name = new string[] {"*"};
190193
}
191194

192195
Name = Utils.ProcessNameWildcards(Name, removeWildcardEntries:false, out string[] errorMsgs, out bool nameContainsWildcard);
@@ -205,11 +208,48 @@ private void ProcessResourceNameParameterSet()
205208
if (Name.Length == 0)
206209
{
207210
return;
208-
}
211+
}
212+
213+
// determine/parse out Version param
214+
VersionType versionType = VersionType.VersionRange;
215+
NuGetVersion nugetVersion = null;
216+
VersionRange versionRange = null;
217+
218+
if (Version != null)
219+
{
220+
if (!NuGetVersion.TryParse(Version, out nugetVersion))
221+
{
222+
if (Version.Trim().Equals("*"))
223+
{
224+
versionRange = VersionRange.All;
225+
versionType = VersionType.VersionRange;
226+
}
227+
else if (!VersionRange.TryParse(Version, out versionRange))
228+
{
229+
WriteError(new ErrorRecord(
230+
new ArgumentException("Argument for -Version parameter is not in the proper format"),
231+
"IncorrectVersionFormat",
232+
ErrorCategory.InvalidArgument,
233+
this));
234+
return;
235+
}
236+
}
237+
else
238+
{
239+
versionType = VersionType.SpecificVersion;
240+
}
241+
}
242+
else
243+
{
244+
versionType = VersionType.NoVersion;
245+
}
209246

210247
foreach (PSResourceInfo pkg in _findHelper.FindByResourceName(
211248
name: Name,
212249
type: Type,
250+
versionRange: versionRange,
251+
nugetVersion: nugetVersion,
252+
versionType: versionType,
213253
version: Version,
214254
prerelease: Prerelease,
215255
tag: Tag,

src/code/IServerAPICalls.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ public interface IServerAPICalls
3434
/// - Include prerelease: http://www.powershellgallery.com/api/v2/FindPackagesById()?id='PowerShellGet'
3535
/// Implementation Note: Need to filter further for latest version (prerelease or non-prerelease dependening on user preference)
3636
/// </summary>
37-
/// // TODO: change repository from string to PSRepositoryInfo
3837
string FindName(string packageName, bool includePrerelease, ResourceType type, out ExceptionDispatchInfo edi);
3938

39+
string FindNameWithTag(string packageName, string[] tags, bool includePrerelease, ResourceType type, out ExceptionDispatchInfo edi);
40+
4041
/// <summary>
4142
/// Find method which allows for searching for single name with version range.
4243
/// Name: no wildcard support
@@ -48,6 +49,8 @@ public interface IServerAPICalls
4849
/// </summary>
4950
string[] FindNameGlobbing(string packageName, bool includePrerelease, ResourceType type, out ExceptionDispatchInfo edi);
5051

52+
string[] FindNameGlobbingWithTag(string packageName, string[] tags, bool includePrerelease, ResourceType type, out ExceptionDispatchInfo edi);
53+
5154
/// <summary>
5255
/// Find method which allows for searching for single name with specific version.
5356
/// Name: no wildcard support
@@ -65,6 +68,8 @@ public interface IServerAPICalls
6568
/// API call: http://www.powershellgallery.com/api/v2/Packages(Id='PowerShellGet', Version='2.2.5')
6669
/// </summary>
6770
string FindVersion(string packageName, string version, ResourceType type, out ExceptionDispatchInfo edi);
71+
72+
string FindVersionWithTag(string packageName, string version, string[] tags, ResourceType type, out ExceptionDispatchInfo edi);
6873

6974

7075
/// <summary>

src/code/InstallHelper.cs

+20
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ internal class InstallHelper
4242
private readonly PSCmdlet _cmdletPassedIn;
4343
private List<string> _pathsToInstallPkg;
4444
private VersionRange _versionRange;
45+
private NuGetVersion _nugetVersion;
46+
private VersionType _versionType;
4547
private string _versionString;
4648
private bool _prerelease;
4749
private bool _acceptLicense;
@@ -126,6 +128,21 @@ public IEnumerable<PSResourceInfo> InstallPackages(
126128
_pathsToInstallPkg = pathsToInstallPkg;
127129
_tmpPath = tmpPath ?? Path.GetTempPath();
128130

131+
bool parsedAsNuGetVersion = NuGetVersion.TryParse(_versionString, out _nugetVersion);
132+
if (parsedAsNuGetVersion)
133+
{
134+
_versionType = VersionType.SpecificVersion;
135+
}
136+
else if (!parsedAsNuGetVersion && _versionRange == null)
137+
{
138+
_versionType = VersionType.NoVersion;
139+
}
140+
else
141+
{
142+
// versionRange != null
143+
_versionType = VersionType.VersionRange;
144+
}
145+
129146
// Create list of installation paths to search.
130147
_pathsToSearch = new List<string>();
131148
_pkgNamesToInstall = names.ToList();
@@ -242,6 +259,9 @@ private List<PSResourceInfo> ProcessRepositories(
242259
List<PSResourceInfo> pkgsFromRepoToInstall = findHelper.FindByResourceName(
243260
name: _pkgNamesToInstall.ToArray(),
244261
type: ResourceType.None,
262+
versionRange: _versionRange,
263+
nugetVersion: _nugetVersion,
264+
versionType: _versionType,
245265
version: _versionRange?.OriginalString,
246266
prerelease: _prerelease,
247267
tag: null,

src/code/PSGetException.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,12 @@ public JsonParsingException(string message)
2929
{
3030
}
3131
}
32-
}
32+
33+
public class SpecifiedTagsNotFoundException : Exception
34+
{
35+
public SpecifiedTagsNotFoundException(string message)
36+
: base (message)
37+
{
38+
}
39+
}
40+
}

src/code/PublishPSResource.cs

+29-9
Original file line numberDiff line numberDiff line change
@@ -765,23 +765,43 @@ private bool CheckDependenciesExist(Hashtable dependencies, string repositoryNam
765765
depVersion = string.IsNullOrWhiteSpace(depVersion) ? "*" : depVersion;
766766

767767
VersionRange versionRange = null;
768-
if (!Utils.TryParseVersionOrVersionRange(depVersion, out versionRange))
768+
VersionType versionType = VersionType.VersionRange;
769+
NuGetVersion nugetVersion = null;
770+
771+
if (depVersion != null)
772+
{
773+
if (!NuGetVersion.TryParse(depVersion, out nugetVersion))
774+
{
775+
if (depVersion.Trim().Equals("*"))
776+
{
777+
versionRange = VersionRange.All;
778+
versionType = VersionType.VersionRange;
779+
}
780+
else if (!VersionRange.TryParse(depVersion, out versionRange))
781+
{
782+
ThrowTerminatingError(new ErrorRecord(
783+
new ArgumentException("Argument for -Version parameter is not in the proper format"),
784+
"IncorrectVersionFormat",
785+
ErrorCategory.InvalidArgument,
786+
this));
787+
}
788+
}
789+
else
790+
{
791+
versionType = VersionType.SpecificVersion;
792+
}
793+
}
794+
else
769795
{
770-
// This should never be true because Test-ModuleManifest will throw an error if dependency versions are incorrectly formatted
771-
// This is being left as a safeguard for parsing a version from a string to a version range.
772-
ThrowTerminatingError(new ErrorRecord(
773-
new ArgumentException(string.Format("Error parsing dependency version {0}, from the module {1}", depVersion, depName)),
774-
"IncorrectVersionFormat",
775-
ErrorCategory.InvalidArgument,
776-
this));
796+
versionType = VersionType.NoVersion;
777797
}
778798

779799
// Search for and return the dependency if it's in the repository.
780800
FindHelper findHelper = new FindHelper(_cancellationToken, this, _networkCredential);
781801
bool depPrerelease = depVersion.Contains("-");
782802

783803
var repository = new[] { repositoryName };
784-
var dependencyFound = findHelper.FindByResourceName(depName, ResourceType.Module, depVersion, depPrerelease, null, repository, false);
804+
var dependencyFound = findHelper.FindByResourceName(depName, ResourceType.Module, versionRange, nugetVersion, versionType, depVersion, depPrerelease, null, repository, false);
785805
if (dependencyFound == null || !dependencyFound.Any())
786806
{
787807
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);

src/code/ServerApiCall.cs

+6
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ public ServerApiCall(PSRepositoryInfo repository, NetworkCredential networkCrede
6464
/// </summary>
6565
public abstract string FindName(string packageName, bool includePrerelease, ResourceType type, out ExceptionDispatchInfo edi);
6666

67+
public abstract string FindNameWithTag(string packageName, string[] tags, bool includePrerelease, ResourceType type, out ExceptionDispatchInfo edi);
68+
6769
/// <summary>
6870
/// Find method which allows for searching for single name with wildcards and returns latest version.
6971
/// Name: supports wildcards
@@ -73,6 +75,8 @@ public ServerApiCall(PSRepositoryInfo repository, NetworkCredential networkCrede
7375
/// Implementation Note: filter additionally and verify ONLY package name was a match.
7476
/// </summary>
7577
public abstract string[] FindNameGlobbing(string packageName, bool includePrerelease, ResourceType type, out ExceptionDispatchInfo edi);
78+
79+
public abstract string[] FindNameGlobbingWithTag(string packageName, string[] tags, bool includePrerelease, ResourceType type, out ExceptionDispatchInfo edi);
7680
/// <summary>
7781
/// Find method which allows for searching for single name with version range.
7882
/// Name: no wildcard support
@@ -93,6 +97,8 @@ public ServerApiCall(PSRepositoryInfo repository, NetworkCredential networkCrede
9397
/// </summary>
9498
public abstract string FindVersion(string packageName, string version, ResourceType type, out ExceptionDispatchInfo edi);
9599

100+
public abstract string FindVersionWithTag(string packageName, string version, string[] tags, ResourceType type, out ExceptionDispatchInfo edi);
101+
96102
/** INSTALL APIS **/
97103

98104
/// <summary>

src/code/UpdatePSResource.cs

+36-14
Original file line numberDiff line numberDiff line change
@@ -167,24 +167,41 @@ protected override void BeginProcessing()
167167

168168
protected override void ProcessRecord()
169169
{
170-
VersionRange versionRange;
170+
// determine/parse out Version param
171+
VersionType versionType = VersionType.VersionRange;
172+
NuGetVersion nugetVersion = null;
173+
VersionRange versionRange = null;
171174

172-
// handle case where Version == null
173-
if (Version == null) {
174-
versionRange = VersionRange.All;
175+
if (Version != null)
176+
{
177+
if (!NuGetVersion.TryParse(Version, out nugetVersion))
178+
{
179+
if (Version.Trim().Equals("*"))
180+
{
181+
versionRange = VersionRange.All;
182+
versionType = VersionType.VersionRange;
183+
}
184+
else if (!VersionRange.TryParse(Version, out versionRange))
185+
{
186+
WriteError(new ErrorRecord(
187+
new ArgumentException("Argument for -Version parameter is not in the proper format"),
188+
"IncorrectVersionFormat",
189+
ErrorCategory.InvalidArgument,
190+
this));
191+
return;
192+
}
193+
}
194+
else
195+
{
196+
versionType = VersionType.SpecificVersion;
197+
}
175198
}
176-
else if (!Utils.TryParseVersionOrVersionRange(Version, out versionRange))
199+
else
177200
{
178-
// Only returns false if the range was incorrectly formatted and couldn't be parsed.
179-
WriteError(new ErrorRecord(
180-
new PSInvalidOperationException("Cannot parse Version parameter provided into VersionRange"),
181-
"ErrorParsingVersionParamIntoVersionRange",
182-
ErrorCategory.InvalidArgument,
183-
this));
184-
return;
201+
versionType = VersionType.NoVersion;
185202
}
186203

187-
var namesToUpdate = ProcessPackageNames(Name, versionRange);
204+
var namesToUpdate = ProcessPackageNames(Name, versionRange, nugetVersion, versionType);
188205

189206
if (namesToUpdate.Length == 0)
190207
{
@@ -253,7 +270,9 @@ protected override void EndProcessing()
253270
/// </Summary>
254271
private string[] ProcessPackageNames(
255272
string[] namesToProcess,
256-
VersionRange versionRange)
273+
VersionRange versionRange,
274+
NuGetVersion nuGetVersion,
275+
VersionType versionType)
257276
{
258277
namesToProcess = Utils.ProcessNameWildcards(
259278
pkgNames: namesToProcess,
@@ -310,6 +329,9 @@ private string[] ProcessPackageNames(
310329
foreach (var foundResource in _findHelper.FindByResourceName(
311330
name: installedPackages.Keys.ToArray(),
312331
type: ResourceType.None,
332+
versionRange: versionRange,
333+
nugetVersion: nuGetVersion,
334+
versionType: versionType,
313335
version: Version,
314336
prerelease: Prerelease,
315337
tag: null,

src/code/V2ResponseUtil.cs

+7
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ public override IEnumerable<PSResourceResult> ConvertToPSResourceResult(string[]
3939
foreach (string response in responses)
4040
{
4141
var elemList = ConvertResponseToXML(response);
42+
if (elemList.Length == 0)
43+
{
44+
// this indicates we got a non-empty, XML response (as noticed for V2 server) but it's not a response that's meaningful (contains 'properties')
45+
string errorMsg = $"Response didn't contain properties element";
46+
yield return new PSResourceResult(returnedObject: null, errorMsg: errorMsg, isTerminatingError: false);
47+
}
48+
4249
foreach (var element in elemList)
4350
{
4451
if (!PSResourceInfo.TryConvertFromXml(element, out PSResourceInfo psGetInfo, repository.Name, out string errorMsg))

0 commit comments

Comments
 (0)