Skip to content

Commit 0309ae0

Browse files
authored
Allow .psd1 to be passed into -RequiredResourceFile (#610)
1 parent 33f68b6 commit 0309ae0

9 files changed

+125
-33
lines changed

src/code/GetHelper.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ internal class GetHelper
2121

2222
private readonly PSCmdlet _cmdletPassedIn;
2323
private readonly Dictionary<string, PSResourceInfo> _scriptDictionary;
24+
public const string PSScriptFileExt = ".ps1";
2425

2526
#endregion
2627

@@ -222,7 +223,7 @@ private static string GetResourceNameFromPath(string path)
222223
// ./Modules/Microsoft.PowerShell.Test-Module : Microsoft.PowerShell.Test-Module
223224
// ./Scripts/Microsoft.PowerShell.Test-Script.ps1 : Microsoft.PowerShell.Test-Script
224225
var resourceName = Path.GetFileName(path);
225-
return Path.GetExtension(resourceName).Equals(".ps1", StringComparison.OrdinalIgnoreCase)
226+
return Path.GetExtension(resourceName).Equals(PSScriptFileExt, StringComparison.OrdinalIgnoreCase)
226227
? Path.GetFileNameWithoutExtension(resourceName) : resourceName;
227228
}
228229

src/code/InstallHelper.cs

+12-10
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ namespace Microsoft.PowerShell.PowerShellGet.Cmdlets
2828
/// Install helper class
2929
/// </summary>
3030
internal class InstallHelper : PSCmdlet
31-
{
31+
{
3232
#region Members
3333

34+
public const string PSDataFileExt = ".psd1";
35+
public const string PSScriptFileExt = ".ps1";
3436
private const string MsgRepositoryNotTrusted = "Untrusted repository";
3537
private const string MsgInstallUntrustedPackage = "You are installing the modules from an untrusted repository. If you trust this repository, change its Trusted value by running the Set-PSResourceRepository cmdlet. Are you sure you want to install the PSresource from '{0}' ?";
3638

@@ -461,8 +463,8 @@ private List<PSResourceInfo> InstallPackage(
461463
string tempDirNameVersion = isLocalRepo ? tempInstallPath : Path.Combine(tempInstallPath, pkgIdentity.Id.ToLower(), newVersion);
462464
var version4digitNoPrerelease = pkgIdentity.Version.Version.ToString();
463465
string moduleManifestVersion = string.Empty;
464-
var scriptPath = Path.Combine(tempDirNameVersion, pkg.Name + ".ps1");
465-
var modulePath = Path.Combine(tempDirNameVersion, pkg.Name + ".psd1");
466+
var scriptPath = Path.Combine(tempDirNameVersion, pkg.Name + PSScriptFileExt);
467+
var modulePath = Path.Combine(tempDirNameVersion, pkg.Name + PSDataFileExt);
466468
// Check if the package is a module or a script
467469
var isModule = File.Exists(modulePath);
468470

@@ -497,7 +499,7 @@ private List<PSResourceInfo> InstallPackage(
497499

498500
if (isModule)
499501
{
500-
var moduleManifest = Path.Combine(tempDirNameVersion, pkgIdentity.Id + ".psd1");
502+
var moduleManifest = Path.Combine(tempDirNameVersion, pkgIdentity.Id + PSDataFileExt);
501503
if (!File.Exists(moduleManifest))
502504
{
503505
var message = String.Format("{0} package could not be installed with error: Module manifest file: {1} does not exist. This is not a valid PowerShell module.", pkgIdentity.Id, moduleManifest);
@@ -509,7 +511,7 @@ private List<PSResourceInfo> InstallPackage(
509511
continue;
510512
}
511513

512-
if (!Utils.TryParseModuleManifest(moduleManifest, _cmdletPassedIn, out Hashtable parsedMetadataHashtable))
514+
if (!Utils.TryParsePSDataFile(moduleManifest, _cmdletPassedIn, out Hashtable parsedMetadataHashtable))
513515
{
514516
// Ran into errors parsing the module manifest file which was found in Utils.ParseModuleManifest() and written.
515517
continue;
@@ -878,16 +880,16 @@ private void MoveFilesIntoInstallPath(
878880
Utils.MoveFiles(Path.Combine(dirNameVersion, scriptXML), Path.Combine(installPath, "InstalledScriptInfos", scriptXML));
879881

880882
// Need to delete old script file, if that exists
881-
_cmdletPassedIn.WriteVerbose(string.Format("Checking if path '{0}' exists: ", File.Exists(Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1"))));
882-
if (File.Exists(Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1")))
883+
_cmdletPassedIn.WriteVerbose(string.Format("Checking if path '{0}' exists: ", File.Exists(Path.Combine(finalModuleVersionDir, pkgInfo.Name + PSScriptFileExt))));
884+
if (File.Exists(Path.Combine(finalModuleVersionDir, pkgInfo.Name + PSScriptFileExt)))
883885
{
884886
_cmdletPassedIn.WriteVerbose(string.Format("Deleting script file"));
885-
File.Delete(Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1"));
887+
File.Delete(Path.Combine(finalModuleVersionDir, pkgInfo.Name + PSScriptFileExt));
886888
}
887889
}
888890

889-
_cmdletPassedIn.WriteVerbose(string.Format("Moving '{0}' to '{1}'", scriptPath, Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1")));
890-
Utils.MoveFiles(scriptPath, Path.Combine(finalModuleVersionDir, pkgInfo.Name + ".ps1"));
891+
_cmdletPassedIn.WriteVerbose(string.Format("Moving '{0}' to '{1}'", scriptPath, Path.Combine(finalModuleVersionDir, pkgInfo.Name + PSScriptFileExt)));
892+
Utils.MoveFiles(scriptPath, Path.Combine(finalModuleVersionDir, pkgInfo.Name + PSScriptFileExt));
891893
}
892894
}
893895

src/code/InstallPSResource.cs

+62-8
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class InstallPSResource : PSCmdlet
118118
public PSResourceInfo InputObject { get; set; }
119119

120120
/// <summary>
121-
/// Installs resources based on input from a JSON file.
121+
/// Installs resources based on input from a .psd1 (hashtable) or .json file.
122122
/// </summary>
123123
[Parameter(ParameterSetName = RequiredResourceFileParameterSet)]
124124
[ValidateNotNullOrEmpty]
@@ -138,13 +138,31 @@ public String RequiredResourceFile
138138

139139
if (!File.Exists(resolvedPath))
140140
{
141-
var exMessage = String.Format("The RequiredResourceFile does not exist. Please try specifying a path to a valid .json file");
141+
var exMessage = String.Format("The RequiredResourceFile does not exist. Please try specifying a path to a valid .json or .psd1 file");
142142
var ex = new ArgumentException(exMessage);
143143
var RequiredResourceFileDoesNotExist = new ErrorRecord(ex, "RequiredResourceFileDoesNotExist", ErrorCategory.ObjectNotFound, null);
144144

145145
ThrowTerminatingError(RequiredResourceFileDoesNotExist);
146146
}
147147

148+
if (resolvedPath.EndsWith(".json", StringComparison.InvariantCultureIgnoreCase))
149+
{
150+
_resourceFileType = ResourceFileType.JsonFile;
151+
}
152+
else if (resolvedPath.EndsWith(".psd1", StringComparison.InvariantCultureIgnoreCase))
153+
{
154+
_resourceFileType = ResourceFileType.PSDataFile;
155+
}
156+
else
157+
{
158+
// Throw here because no further processing can be done.
159+
var exMessage = String.Format("The RequiredResourceFile must have either a '.json' or '.psd1' extension. Please try specifying a path to a valid .json or .psd1 file");
160+
var ex = new ArgumentException(exMessage);
161+
var RequiredResourceFileNotValid = new ErrorRecord(ex, "RequiredResourceFileNotValid", ErrorCategory.ObjectNotFound, null);
162+
163+
ThrowTerminatingError(RequiredResourceFileNotValid);
164+
}
165+
148166
_requiredResourceFile = resolvedPath;
149167
}
150168
}
@@ -176,6 +194,17 @@ public String RequiredResourceFile
176194

177195
#endregion
178196

197+
#region Enums
198+
199+
private enum ResourceFileType
200+
{
201+
UnknownFile,
202+
JsonFile,
203+
PSDataFile
204+
}
205+
206+
#endregion
207+
179208
#region Members
180209

181210
private const string NameParameterSet = "NameParameterSet";
@@ -188,6 +217,7 @@ public String RequiredResourceFile
188217
private Hashtable _requiredResourceHash;
189218
VersionRange _versionRange;
190219
InstallHelper _installHelper;
220+
ResourceFileType _resourceFileType;
191221

192222
#endregion
193223

@@ -252,7 +282,7 @@ protected override void ProcessRecord()
252282
break;
253283

254284
case RequiredResourceFileParameterSet:
255-
/* json file contents should look like:
285+
/* .json file contents should look like:
256286
{
257287
"Pester": {
258288
"allowPrerelease": true,
@@ -262,28 +292,52 @@ protected override void ProcessRecord()
262292
}
263293
}
264294
*/
265-
295+
296+
/* .psd1 file contents should look like:
297+
@{
298+
"Configuration" = @{ version = "[4.4.2,4.7.0]" }
299+
"Pester" = @{
300+
version = "[4.4.2,4.7.0]"
301+
repository = PSGallery
302+
credential = $cred
303+
prerelease = $true
304+
}
305+
}
306+
*/
307+
266308
string requiredResourceFileStream = string.Empty;
267309
using (StreamReader sr = new StreamReader(_requiredResourceFile))
268310
{
269311
requiredResourceFileStream = sr.ReadToEnd();
270312
}
271313

272-
Hashtable pkgsInJsonFile = null;
314+
Hashtable pkgsInFile = null;
273315
try
274316
{
275-
pkgsInJsonFile = Utils.ConvertJsonToHashtable(this, requiredResourceFileStream);
317+
if (_resourceFileType.Equals(ResourceFileType.JsonFile))
318+
{
319+
pkgsInFile = Utils.ConvertJsonToHashtable(this, requiredResourceFileStream);
320+
}
321+
else
322+
{
323+
// must be a .psd1 file
324+
if (!Utils.TryParsePSDataFile(_requiredResourceFile, this, out pkgsInFile))
325+
{
326+
// Ran into errors parsing the .psd1 file which was found in Utils.TryParsePSDataFile() and written.
327+
return;
328+
}
329+
}
276330
}
277331
catch (Exception)
278332
{
279-
var exMessage = String.Format("Argument for parameter -RequiredResourceFile is not in proper json format. Make sure argument is either a valid json file.");
333+
var exMessage = String.Format("Argument for parameter -RequiredResourceFile is not in proper json or hashtable format. Make sure argument is either a valid .json or .psd1 file.");
280334
var ex = new ArgumentException(exMessage);
281335
var RequiredResourceFileNotInProperJsonFormat = new ErrorRecord(ex, "RequiredResourceFileNotInProperJsonFormat", ErrorCategory.InvalidData, null);
282336

283337
ThrowTerminatingError(RequiredResourceFileNotInProperJsonFormat);
284338
}
285339

286-
RequiredResourceHelper(pkgsInJsonFile);
340+
RequiredResourceHelper(pkgsInFile);
287341
break;
288342

289343
case RequiredResourceParameterSet:

src/code/PublishPSResource.cs

+7-5
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public string Path
6363
{
6464
_path = resolvedPath;
6565
}
66-
else if (File.Exists(resolvedPath) && resolvedPath.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase))
66+
else if (File.Exists(resolvedPath) && resolvedPath.EndsWith(PSDataFileExt, StringComparison.OrdinalIgnoreCase))
6767
{
6868
_path = resolvedPath;
6969
}
@@ -163,6 +163,8 @@ public PSCredential ProxyCredential {
163163
private NuGetVersion _pkgVersion;
164164
private string _pkgName;
165165
private static char[] _PathSeparators = new [] { System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar };
166+
public const string PSDataFileExt = ".psd1";
167+
public const string PSScriptFileExt = ".ps1";
166168

167169
#endregion
168170

@@ -179,7 +181,7 @@ protected override void ProcessRecord()
179181
{
180182
// Returns the name of the file or the name of the directory, depending on path
181183
var pkgFileOrDir = new DirectoryInfo(_path);
182-
bool isScript = _path.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase);
184+
bool isScript = _path.EndsWith(PSScriptFileExt, StringComparison.OrdinalIgnoreCase);
183185

184186
if (!ShouldProcess(string.Format("Publish resource '{0}' from the machine", _path)))
185187
{
@@ -233,7 +235,7 @@ protected override void ProcessRecord()
233235
else
234236
{
235237
_pkgName = pkgFileOrDir.Name;
236-
resourceFilePath = System.IO.Path.Combine(_path, _pkgName + ".psd1");
238+
resourceFilePath = System.IO.Path.Combine(_path, _pkgName + PSDataFileExt);
237239

238240
// Validate that there's a module manifest
239241
if (!File.Exists(resourceFilePath))
@@ -332,7 +334,7 @@ protected override void ProcessRecord()
332334
if (isScript)
333335
{
334336
// copy the script file to the temp directory
335-
File.Copy(_path, System.IO.Path.Combine(outputDir, _pkgName + ".ps1"), true);
337+
File.Copy(_path, System.IO.Path.Combine(outputDir, _pkgName + PSDataFileExt), true);
336338
}
337339
else
338340
{
@@ -470,7 +472,7 @@ private string CreateNuspec(
470472
if (!isScript)
471473
{
472474
// Parse the module manifest and *replace* the passed-in metadata with the module manifest metadata.
473-
if (!Utils.TryParseModuleManifest(
475+
if (!Utils.TryParsePSDataFile(
474476
moduleFileInfo: filePath,
475477
cmdletPassedIn: this,
476478
parsedMetadataHashtable: out parsedMetadataHash))

src/code/UninstallPSResource.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public sealed class UninstallPSResource : PSCmdlet
6060

6161
private const string NameParameterSet = "NameParameterSet";
6262
private const string InputObjectParameterSet = "InputObjectParameterSet";
63+
public const string PSScriptFileExt = ".ps1";
6364
public static readonly string OsPlatform = System.Runtime.InteropServices.RuntimeInformation.OSDescription;
6465
VersionRange _versionRange;
6566
List<string> _pathsToSearch = new List<string>();
@@ -180,7 +181,7 @@ private bool UninstallPkgHelper()
180181
}
181182

182183
ErrorRecord errRecord = null;
183-
if (pkgPath.EndsWith(".ps1"))
184+
if (pkgPath.EndsWith(PSScriptFileExt))
184185
{
185186
successfullyUninstalled = UninstallScriptHelper(pkgPath, pkgName, out errRecord);
186187
}

src/code/Utils.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ internal static class Utils
2323
{
2424
#region String fields
2525

26-
public static readonly string[] EmptyStrArray = Array.Empty<string>();
27-
26+
public static readonly string[] EmptyStrArray = Array.Empty<string>();
27+
public const string PSDataFileExt = ".psd1";
2828
private const string ConvertJsonToHashtableScript = @"
2929
param (
3030
[string] $json
@@ -728,7 +728,7 @@ private static void GetStandardPlatformPaths(
728728

729729
#region Manifest methods
730730

731-
public static bool TryParseModuleManifest(
731+
public static bool TryParsePSDataFile(
732732
string moduleFileInfo,
733733
PSCmdlet cmdletPassedIn,
734734
out Hashtable parsedMetadataHashtable)
@@ -738,7 +738,7 @@ public static bool TryParseModuleManifest(
738738

739739
// A script will already have the metadata parsed into the parsedMetadatahash,
740740
// a module will still need the module manifest to be parsed.
741-
if (moduleFileInfo.EndsWith(".psd1", StringComparison.OrdinalIgnoreCase))
741+
if (moduleFileInfo.EndsWith(PSDataFileExt, StringComparison.OrdinalIgnoreCase))
742742
{
743743
// Parse the module manifest
744744
var ast = Parser.ParseFile(

test/InstallPSResource.Tests.ps1

+21-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Describe 'Test Install-PSResource for Module' {
1212
$NuGetGalleryName = Get-NuGetGalleryName
1313
$testModuleName = "TestModule"
1414
$RequiredResourceJSONFileName = "TestRequiredResourceFile.json"
15+
$RequiredResourcePSD1FileName = "TestRequiredResourceFile.psd1"
1516
Get-NewPSResourceRepositoryFile
1617
Register-LocalRepos
1718
}
@@ -381,10 +382,28 @@ Describe 'Test Install-PSResource for Module' {
381382
$res3.Version | Should -Be "0.0.5"
382383
}
383384

385+
It "Install modules using -RequiredResourceFile with PSD1 file" {
386+
$rrFilePSD1 = Join-Path -Path $psscriptroot -ChildPath $RequiredResourcePSD1FileName
387+
388+
Install-PSResource -RequiredResourceFile $rrFilePSD1
389+
390+
$res1 = Get-Module "TestModule" -ListAvailable
391+
$res1.Name | Should -Be "TestModule"
392+
$res1.Version | Should -Be "1.3.0"
393+
394+
$res2 = Get-Module "TestModulePrerelease" -ListAvailable
395+
$res2.Name | Should -Be "TestModulePrerelease"
396+
$res2.Version | Should -Be "0.0.1"
397+
398+
$res3 = Get-Module "TestModule99" -ListAvailable
399+
$res3.Name | Should -Be "TestModule99"
400+
$res3.Version | Should -Be "0.0.5"
401+
}
402+
384403
It "Install modules using -RequiredResourceFile with JSON file" {
385-
$rrFileJSON = ".\$RequiredResourceJSONFileName"
404+
$rrFileJSON = Join-Path -Path $psscriptroot -ChildPath $RequiredResourceJSONFileName
386405

387-
Install-PSResource -RequiredResourceFile $rrFileJSON -Verbose
406+
Install-PSResource -RequiredResourceFile $rrFileJSON
388407

389408
$res1 = Get-Module "TestModule" -ListAvailable
390409
$res1.Name | Should -Be "TestModule"

test/TestRequiredResourceFile.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,5 @@
88
"repository": "PoshTestGallery",
99
"prerelease": "true"
1010
},
11-
"TestModule99": {
12-
}
11+
"TestModule99": {}
1312
}

test/TestRequiredResourceFile.psd1

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
@{
2+
TestModule = @{
3+
version = "[0.0.1,1.3.0]"
4+
repository = "PoshTestGallery"
5+
}
6+
7+
TestModulePrerelease = @{
8+
version = "[0.0.0,0.0.5]"
9+
repository = "PoshTestGallery"
10+
prerelease = "true"
11+
}
12+
13+
TestModule99 = @{}
14+
}

0 commit comments

Comments
 (0)