diff --git a/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs b/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs
index 8e1afd96929..b0e1267973e 100644
--- a/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs
+++ b/src/System.Management.Automation/engine/Modules/NewModuleManifestCommand.cs
@@ -495,6 +495,26 @@ public object PrivateData
[ValidateNotNullOrEmpty]
public string ReleaseNotes { get; set; }
+ ///
+ /// Gets or sets whether or not the module is a prerelease.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty]
+ public string Prerelease { get; set; }
+
+ ///
+ /// Gets or sets whether or not the module requires explicit user acceptance for install/update/save.
+ ///
+ [Parameter]
+ public SwitchParameter RequireLicenseAcceptance { get; set; } = true;
+
+ ///
+ /// Gets or sets the external module dependencies.
+ ///
+ [Parameter]
+ [ValidateNotNullOrEmpty]
+ public string[] ExternalModuleDependencies { get; set; }
+
///
/// Specify the HelpInfo URI.
///
@@ -1044,65 +1064,65 @@ protected override void EndProcessing()
if (_rootModule == null)
_rootModule = string.Empty;
- BuildModuleManifest(result, "RootModule", Modules.RootModule, !string.IsNullOrEmpty(_rootModule), () => QuoteName(_rootModule), streamWriter);
+ BuildModuleManifest(result, nameof(RootModule), Modules.RootModule, !string.IsNullOrEmpty(_rootModule), () => QuoteName(_rootModule), streamWriter);
- BuildModuleManifest(result, "ModuleVersion", Modules.ModuleVersion, _moduleVersion != null && !string.IsNullOrEmpty(_moduleVersion.ToString()), () => QuoteName(_moduleVersion), streamWriter);
+ BuildModuleManifest(result, nameof(ModuleVersion), Modules.ModuleVersion, _moduleVersion != null && !string.IsNullOrEmpty(_moduleVersion.ToString()), () => QuoteName(_moduleVersion), streamWriter);
- BuildModuleManifest(result, "CompatiblePSEditions", Modules.CompatiblePSEditions, _compatiblePSEditions != null && _compatiblePSEditions.Length > 0, () => QuoteNames(_compatiblePSEditions, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(CompatiblePSEditions), Modules.CompatiblePSEditions, _compatiblePSEditions != null && _compatiblePSEditions.Length > 0, () => QuoteNames(_compatiblePSEditions, streamWriter), streamWriter);
- BuildModuleManifest(result, "GUID", Modules.GUID, !string.IsNullOrEmpty(_guid.ToString()), () => QuoteName(_guid.ToString()), streamWriter);
+ BuildModuleManifest(result, nameof(Modules.GUID), Modules.GUID, !string.IsNullOrEmpty(_guid.ToString()), () => QuoteName(_guid.ToString()), streamWriter);
- BuildModuleManifest(result, "Author", Modules.Author, !string.IsNullOrEmpty(_author), () => QuoteName(Author), streamWriter);
+ BuildModuleManifest(result, nameof(Author), Modules.Author, !string.IsNullOrEmpty(_author), () => QuoteName(Author), streamWriter);
- BuildModuleManifest(result, "CompanyName", Modules.CompanyName, !string.IsNullOrEmpty(_companyName), () => QuoteName(_companyName), streamWriter);
+ BuildModuleManifest(result, nameof(CompanyName), Modules.CompanyName, !string.IsNullOrEmpty(_companyName), () => QuoteName(_companyName), streamWriter);
- BuildModuleManifest(result, "Copyright", Modules.Copyright, !string.IsNullOrEmpty(_copyright), () => QuoteName(_copyright), streamWriter);
+ BuildModuleManifest(result, nameof(Copyright), Modules.Copyright, !string.IsNullOrEmpty(_copyright), () => QuoteName(_copyright), streamWriter);
- BuildModuleManifest(result, "Description", Modules.Description, !string.IsNullOrEmpty(_description), () => QuoteName(_description), streamWriter);
+ BuildModuleManifest(result, nameof(Description), Modules.Description, !string.IsNullOrEmpty(_description), () => QuoteName(_description), streamWriter);
- BuildModuleManifest(result, "PowerShellVersion", Modules.PowerShellVersion, _powerShellVersion != null && !string.IsNullOrEmpty(_powerShellVersion.ToString()), () => QuoteName(_powerShellVersion), streamWriter);
+ BuildModuleManifest(result, nameof(PowerShellVersion), Modules.PowerShellVersion, _powerShellVersion != null && !string.IsNullOrEmpty(_powerShellVersion.ToString()), () => QuoteName(_powerShellVersion), streamWriter);
- BuildModuleManifest(result, "PowerShellHostName", Modules.PowerShellHostName, !string.IsNullOrEmpty(_PowerShellHostName), () => QuoteName(_PowerShellHostName), streamWriter);
+ BuildModuleManifest(result, nameof(PowerShellHostName), Modules.PowerShellHostName, !string.IsNullOrEmpty(_PowerShellHostName), () => QuoteName(_PowerShellHostName), streamWriter);
- BuildModuleManifest(result, "PowerShellHostVersion", Modules.PowerShellHostVersion, _PowerShellHostVersion != null && !string.IsNullOrEmpty(_PowerShellHostVersion.ToString()), () => QuoteName(_PowerShellHostVersion), streamWriter);
+ BuildModuleManifest(result, nameof(PowerShellHostVersion), Modules.PowerShellHostVersion, _PowerShellHostVersion != null && !string.IsNullOrEmpty(_PowerShellHostVersion.ToString()), () => QuoteName(_PowerShellHostVersion), streamWriter);
- BuildModuleManifest(result, "DotNetFrameworkVersion", StringUtil.Format(Modules.DotNetFrameworkVersion, Modules.PrerequisiteForDesktopEditionOnly), _DotNetFrameworkVersion != null && !string.IsNullOrEmpty(_DotNetFrameworkVersion.ToString()), () => QuoteName(_DotNetFrameworkVersion), streamWriter);
+ BuildModuleManifest(result, nameof(DotNetFrameworkVersion), StringUtil.Format(Modules.DotNetFrameworkVersion, Modules.PrerequisiteForDesktopEditionOnly), _DotNetFrameworkVersion != null && !string.IsNullOrEmpty(_DotNetFrameworkVersion.ToString()), () => QuoteName(_DotNetFrameworkVersion), streamWriter);
- BuildModuleManifest(result, "CLRVersion", StringUtil.Format(Modules.CLRVersion, Modules.PrerequisiteForDesktopEditionOnly), _ClrVersion != null && !string.IsNullOrEmpty(_ClrVersion.ToString()), () => QuoteName(_ClrVersion), streamWriter);
+ BuildModuleManifest(result, nameof(Modules.CLRVersion), StringUtil.Format(Modules.CLRVersion, Modules.PrerequisiteForDesktopEditionOnly), _ClrVersion != null && !string.IsNullOrEmpty(_ClrVersion.ToString()), () => QuoteName(_ClrVersion), streamWriter);
- BuildModuleManifest(result, "ProcessorArchitecture", Modules.ProcessorArchitecture, _processorArchitecture.HasValue, () => QuoteName(_processorArchitecture.ToString()), streamWriter);
+ BuildModuleManifest(result, nameof(ProcessorArchitecture), Modules.ProcessorArchitecture, _processorArchitecture.HasValue, () => QuoteName(_processorArchitecture.ToString()), streamWriter);
- BuildModuleManifest(result, "RequiredModules", Modules.RequiredModules, _requiredModules != null && _requiredModules.Length > 0, () => QuoteModules(_requiredModules, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(RequiredModules), Modules.RequiredModules, _requiredModules != null && _requiredModules.Length > 0, () => QuoteModules(_requiredModules, streamWriter), streamWriter);
- BuildModuleManifest(result, "RequiredAssemblies", Modules.RequiredAssemblies, _requiredAssemblies != null, () => QuoteFiles(_requiredAssemblies, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(RequiredAssemblies), Modules.RequiredAssemblies, _requiredAssemblies != null, () => QuoteFiles(_requiredAssemblies, streamWriter), streamWriter);
- BuildModuleManifest(result, "ScriptsToProcess", Modules.ScriptsToProcess, _scripts != null, () => QuoteFiles(_scripts, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(ScriptsToProcess), Modules.ScriptsToProcess, _scripts != null, () => QuoteFiles(_scripts, streamWriter), streamWriter);
- BuildModuleManifest(result, "TypesToProcess", Modules.TypesToProcess, _types != null, () => QuoteFiles(_types, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(TypesToProcess), Modules.TypesToProcess, _types != null, () => QuoteFiles(_types, streamWriter), streamWriter);
- BuildModuleManifest(result, "FormatsToProcess", Modules.FormatsToProcess, _formats != null, () => QuoteFiles(_formats, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(FormatsToProcess), Modules.FormatsToProcess, _formats != null, () => QuoteFiles(_formats, streamWriter), streamWriter);
- BuildModuleManifest(result, "NestedModules", Modules.NestedModules, _nestedModules != null, () => QuoteModules(PreProcessModuleSpec(_nestedModules), streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(NestedModules), Modules.NestedModules, _nestedModules != null, () => QuoteModules(PreProcessModuleSpec(_nestedModules), streamWriter), streamWriter);
- BuildModuleManifest(result, "FunctionsToExport", Modules.FunctionsToExport, true, () => QuoteNames(_exportedFunctions, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(FunctionsToExport), Modules.FunctionsToExport, true, () => QuoteNames(_exportedFunctions, streamWriter), streamWriter);
- BuildModuleManifest(result, "CmdletsToExport", Modules.CmdletsToExport, true, () => QuoteNames(_exportedCmdlets, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(CmdletsToExport), Modules.CmdletsToExport, true, () => QuoteNames(_exportedCmdlets, streamWriter), streamWriter);
- BuildModuleManifest(result, "VariablesToExport", Modules.VariablesToExport, _exportedVariables != null && _exportedVariables.Length > 0, () => QuoteNames(_exportedVariables, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(VariablesToExport), Modules.VariablesToExport, _exportedVariables != null && _exportedVariables.Length > 0, () => QuoteNames(_exportedVariables, streamWriter), streamWriter);
- BuildModuleManifest(result, "AliasesToExport", Modules.AliasesToExport, true, () => QuoteNames(_exportedAliases, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(AliasesToExport), Modules.AliasesToExport, true, () => QuoteNames(_exportedAliases, streamWriter), streamWriter);
- BuildModuleManifest(result, "DscResourcesToExport", Modules.DscResourcesToExport, _dscResourcesToExport != null && _dscResourcesToExport.Length > 0, () => QuoteNames(_dscResourcesToExport, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(DscResourcesToExport), Modules.DscResourcesToExport, _dscResourcesToExport != null && _dscResourcesToExport.Length > 0, () => QuoteNames(_dscResourcesToExport, streamWriter), streamWriter);
- BuildModuleManifest(result, "ModuleList", Modules.ModuleList, _moduleList != null, () => QuoteModules(_moduleList, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(ModuleList), Modules.ModuleList, _moduleList != null, () => QuoteModules(_moduleList, streamWriter), streamWriter);
- BuildModuleManifest(result, "FileList", Modules.FileList, _miscFiles != null, () => QuoteFiles(_miscFiles, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(FileList), Modules.FileList, _miscFiles != null, () => QuoteFiles(_miscFiles, streamWriter), streamWriter);
BuildPrivateDataInModuleManifest(result, streamWriter);
- BuildModuleManifest(result, "HelpInfoURI", Modules.HelpInfoURI, !string.IsNullOrEmpty(_helpInfoUri), () => QuoteName((_helpInfoUri != null) ? new Uri(_helpInfoUri) : null), streamWriter);
+ BuildModuleManifest(result, nameof(Modules.HelpInfoURI), Modules.HelpInfoURI, !string.IsNullOrEmpty(_helpInfoUri), () => QuoteName((_helpInfoUri != null) ? new Uri(_helpInfoUri) : null), streamWriter);
- BuildModuleManifest(result, "DefaultCommandPrefix", Modules.DefaultCommandPrefix, !string.IsNullOrEmpty(_defaultCommandPrefix), () => QuoteName(_defaultCommandPrefix), streamWriter);
+ BuildModuleManifest(result, nameof(DefaultCommandPrefix), Modules.DefaultCommandPrefix, !string.IsNullOrEmpty(_defaultCommandPrefix), () => QuoteName(_defaultCommandPrefix), streamWriter);
result.Append("}");
result.Append(streamWriter.NewLine);
@@ -1174,7 +1194,7 @@ private void BuildPrivateDataInModuleManifest(StringBuilder result, StreamWriter
{
WriteWarning(Modules.PrivateDataValueTypeShouldBeHashTableWarning);
- BuildModuleManifest(result, "PrivateData", Modules.PrivateData, _privateData != null,
+ BuildModuleManifest(result, nameof(PrivateData), Modules.PrivateData, _privateData != null,
() => QuoteName((string)LanguagePrimitives.ConvertTo(_privateData, typeof(string), CultureInfo.InvariantCulture)),
streamWriter);
}
@@ -1192,11 +1212,14 @@ private void BuildPrivateDataInModuleManifest(StringBuilder result, StreamWriter
_indent = " ";
- BuildModuleManifest(result, "Tags", Modules.Tags, Tags != null && Tags.Length > 0, () => QuoteNames(Tags, streamWriter), streamWriter);
- BuildModuleManifest(result, "LicenseUri", Modules.LicenseUri, LicenseUri != null, () => QuoteName(LicenseUri), streamWriter);
- BuildModuleManifest(result, "ProjectUri", Modules.ProjectUri, ProjectUri != null, () => QuoteName(ProjectUri), streamWriter);
- BuildModuleManifest(result, "IconUri", Modules.IconUri, IconUri != null, () => QuoteName(IconUri), streamWriter);
- BuildModuleManifest(result, "ReleaseNotes", Modules.ReleaseNotes, !string.IsNullOrEmpty(ReleaseNotes), () => QuoteName(ReleaseNotes), streamWriter);
+ BuildModuleManifest(result, nameof(Tags), Modules.Tags, Tags != null && Tags.Length > 0, () => QuoteNames(Tags, streamWriter), streamWriter);
+ BuildModuleManifest(result, nameof(LicenseUri), Modules.LicenseUri, LicenseUri != null, () => QuoteName(LicenseUri), streamWriter);
+ BuildModuleManifest(result, nameof(ProjectUri), Modules.ProjectUri, ProjectUri != null, () => QuoteName(ProjectUri), streamWriter);
+ BuildModuleManifest(result, nameof(IconUri), Modules.IconUri, IconUri != null, () => QuoteName(IconUri), streamWriter);
+ BuildModuleManifest(result, nameof(ReleaseNotes), Modules.ReleaseNotes, !string.IsNullOrEmpty(ReleaseNotes), () => QuoteName(ReleaseNotes), streamWriter);
+ BuildModuleManifest(result, nameof(Prerelease), Modules.Prerelease, !string.IsNullOrEmpty(Prerelease), () => QuoteName(Prerelease), streamWriter);
+ BuildModuleManifest(result, nameof(RequireLicenseAcceptance), Modules.RequireLicenseAcceptance, RequireLicenseAcceptance.IsPresent, () => { return RequireLicenseAcceptance.IsPresent ? "$true" : "$false"; }, streamWriter);
+ BuildModuleManifest(result, nameof(ExternalModuleDependencies), Modules.ExternalModuleDependencies, ExternalModuleDependencies != null && ExternalModuleDependencies.Length > 0, () => QuoteNames(ExternalModuleDependencies, streamWriter), streamWriter);
result.Append(" } ");
result.Append(ManifestComment(StringUtil.Format(Modules.EndOfManifestHashTable, "PSData"), streamWriter));
diff --git a/src/System.Management.Automation/resources/Modules.resx b/src/System.Management.Automation/resources/Modules.resx
index 90f0db5c224..ee0f04b15ce 100644
--- a/src/System.Management.Automation/resources/Modules.resx
+++ b/src/System.Management.Automation/resources/Modules.resx
@@ -426,6 +426,15 @@
ReleaseNotes of this module
+
+ Prerelease string of this module
+
+
+ Flag to indicate whether the module requires explicit user acceptance for install/update/save
+
+
+ External dependent modules of this module
+
End of {0} hashtable
diff --git a/test/powershell/engine/Module/NewModuleManifest.Tests.ps1 b/test/powershell/engine/Module/NewModuleManifest.Tests.ps1
index 945b90f62a1..faacc9f3551 100644
--- a/test/powershell/engine/Module/NewModuleManifest.Tests.ps1
+++ b/test/powershell/engine/Module/NewModuleManifest.Tests.ps1
@@ -1,16 +1,75 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
-Describe "New-ModuleManifest tests" -tags "CI" {
- BeforeEach {
- $null = New-Item -ItemType Directory -Path testdrive:/module
- $testModulePath = "testdrive:/module/test.psd1"
+
+Describe "New-ModuleManifest basic tests" -tags "CI" {
+ BeforeAll {
+ $moduleName = 'test'
+ $modulePath = "$TestDrive/Modules/$moduleName"
+ $manifestPath = Join-Path $modulePath "$moduleName.psd1"
+
+ New-Item -Path "$TestDrive/Modules/$moduleName" -ItemType Directory
}
AfterEach {
- Remove-Item -Recurse -Force -ErrorAction SilentlyContinue testdrive:/module
+ Remove-Item -Path $manifestPath -Force -ErrorAction SilentlyContinue
+ }
+
+ AfterAll {
+ Remove-Item -Path $modulePath -Recurse -Force -ErrorAction SilentlyContinue
}
+ It "Verify manifest fields 1" {
+ New-ModuleManifest -Path $manifestPath
+ $module = Test-ModuleManifest -Path $manifestPath
+ $module.Name | Should -BeExactly "test"
+ $module.ModuleType | Should -BeExactly "Manifest"
+ $module.Version | Should -BeExactly "0.0.1"
+ }
+
+ It "Verify manifest fields 2" {
+ New-ModuleManifest -Path $manifestPath `
+ -Author 'author' `
+ -CompanyName 'company' `
+ -Copyright 'copyright' `
+ -ModuleVersion '1.2.3' `
+ -Description 'description' `
+ -PowerShellVersion '6.0' `
+ -ClrVersion '1.2.3' `
+ -DotNetFrameworkVersion '3.2.1' `
+ -PowerShellHostVersion '1.2.3' `
+ -Tags @('tag1', 'tag2') `
+ -ReleaseNotes 'release note' `
+ -RequiredModules @('PSReadline') `
+ -ExternalModuleDependencies @('PSReadline') `
+ -Prerelease 'prerelease' `
+ -RequireLicenseAcceptance
+
+ $module = Test-ModuleManifest -Path $manifestPath
+ $module.Name | Should -BeExactly "test"
+ $module.Author | Should -BeExactly "author"
+ $module.Version | Should -BeExactly "1.2.3"
+ $module.Description | Should -BeExactly "description"
+ $module.PowerShellVersion | Should -BeExactly "6.0"
+ $module.ClrVersion | Should -BeExactly "1.2.3"
+ $module.DotNetFrameworkVersion | Should -BeExactly "3.2.1"
+ $module.PowerShellHostVersion | Should -BeExactly "1.2.3"
+ $module.Tags | Should -BeExactly @('tag1', 'tag2')
+ $module.ReleaseNotes | Should -BeExactly 'release note'
+ $module.RequiredModules | Should -BeExactly 'PSReadline'
+ $module.PrivateData.PSData.ExternalModuleDependencies | Should -BeExactly 'PSReadline'
+ $module.PrivateData.PSData.Prerelease | Should -BeExactly 'prerelease'
+ $module.PrivateData.PSData.RequireLicenseAcceptance | Should -BeExactly $true
+ }
+}
+
+Describe "New-ModuleManifest tests" -tags "CI" {
BeforeAll {
+ $moduleName = 'test'
+ $modulePath = "$TestDrive/Modules/$moduleName"
+ $manifestPath = Join-Path $modulePath "$moduleName.psd1"
+
+ New-Item -Path "$TestDrive/Modules/$moduleName" -ItemType Directory
+
if ($IsWindows) {
$ExpectedManifestBytes = @(35,13) # CR
} else {
@@ -18,12 +77,21 @@ Describe "New-ModuleManifest tests" -tags "CI" {
}
}
+ AfterEach {
+ Remove-Item -Path $manifestPath -Force -ErrorAction SilentlyContinue
+ }
+
+ AfterAll {
+ Remove-Item -Path $modulePath -Recurse -Force -ErrorAction SilentlyContinue
+ }
+
+
It "Uris with spaces are allowed and escaped correctly" {
$testUri = [Uri]"http://foo.com/hello world"
$absoluteUri = $testUri.AbsoluteUri
- New-ModuleManifest -Path $testModulePath -ProjectUri $testUri -LicenseUri $testUri -IconUri $testUri -HelpInfoUri $testUri
- $module = Test-ModuleManifest -Path $testModulePath
+ New-ModuleManifest -Path $manifestPath -ProjectUri $testUri -LicenseUri $testUri -IconUri $testUri -HelpInfoUri $testUri
+ $module = Test-ModuleManifest -Path $manifestPath
$module.HelpInfoUri | Should -BeExactly $absoluteUri
$module.PrivateData.PSData.IconUri | Should -BeExactly $absoluteUri
$module.PrivateData.PSData.LicenseUri | Should -BeExactly $absoluteUri
@@ -32,8 +100,8 @@ Describe "New-ModuleManifest tests" -tags "CI" {
function TestNewModuleManifestEncoding {
param ([byte[]]$expected)
- New-ModuleManifest -Path $testModulePath
- (Get-Content -AsByteStream -Path $testModulePath -TotalCount $expected.Length) -join ',' | Should -Be ($expected -join ',')
+ New-ModuleManifest -Path $manifestPath
+ (Get-Content -AsByteStream -Path $manifestPath -TotalCount $expected.Length) -join ',' | Should -Be ($expected -join ',')
}
It "Verify module manifest encoding" {
@@ -46,6 +114,6 @@ Describe "New-ModuleManifest tests" -tags "CI" {
It "Relative URIs are not allowed" {
$testUri = [Uri]"../foo"
- { New-ModuleManifest -Path $testModulePath -ProjectUri $testUri -LicenseUri $testUri -IconUri $testUri } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.NewModuleManifestCommand"
+ { New-ModuleManifest -Path $manifestPath -ProjectUri $testUri -LicenseUri $testUri -IconUri $testUri } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.NewModuleManifestCommand"
}
}