mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Support experimental feature in modules
This commit is contained in:
@@ -2027,12 +2027,75 @@ namespace Microsoft.PowerShell.Commands
|
||||
Array.Clear(tmpNestedModules, 0, tmpNestedModules.Length);
|
||||
}
|
||||
|
||||
// Set the private data member for the module if the manifest contains
|
||||
// this member
|
||||
object privateData = null;
|
||||
if (data.Contains("PrivateData"))
|
||||
// Set the private data member for the module if the manifest contains this member
|
||||
object privateData = data["PrivateData"];
|
||||
|
||||
// Validate the 'ExperimentalFeatures' member of the manifest
|
||||
List<ExperimentalFeature> expFeatureList = null;
|
||||
if (privateData is Hashtable hashData && hashData["PSData"] is Hashtable psData)
|
||||
{
|
||||
privateData = data["PrivateData"];
|
||||
if (!GetScalarFromData(psData, moduleManifestPath, "ExperimentalFeatures", manifestProcessingFlags, out Hashtable[] features))
|
||||
{
|
||||
containedErrors = true;
|
||||
if (bailOnFirstError) return null;
|
||||
}
|
||||
|
||||
if (features != null && features.Length > 0)
|
||||
{
|
||||
bool nameMissingOrEmpty = false;
|
||||
var invalidNames = new List<string>();
|
||||
string moduleName = ModuleIntrinsics.GetModuleName(moduleManifestPath);
|
||||
expFeatureList = new List<ExperimentalFeature>(features.Length);
|
||||
|
||||
foreach (var feature in features)
|
||||
{
|
||||
string featureName = feature["Name"] as string;
|
||||
if (String.IsNullOrEmpty(featureName))
|
||||
{
|
||||
nameMissingOrEmpty = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ExperimentalFeature.IsModuleFeatureName(featureName, moduleName))
|
||||
{
|
||||
string featureDescription = feature["Description"] as string;
|
||||
expFeatureList.Add(new ExperimentalFeature(featureName, featureDescription, moduleName,
|
||||
ExperimentalFeature.HasEnabled(featureName)));
|
||||
}
|
||||
else
|
||||
{
|
||||
invalidNames.Add(featureName);
|
||||
}
|
||||
}
|
||||
|
||||
if (nameMissingOrEmpty)
|
||||
{
|
||||
if (writingErrors)
|
||||
{
|
||||
WriteError(new ErrorRecord(new ArgumentException(Modules.ExperimentalFeatureNameMissingOrEmpty),
|
||||
"Modules_ExperimentalFeatureNameMissingOrEmpty",
|
||||
ErrorCategory.InvalidData, null));
|
||||
}
|
||||
|
||||
containedErrors = true;
|
||||
if (bailOnFirstError) { return null; }
|
||||
}
|
||||
|
||||
if (invalidNames.Count > 0)
|
||||
{
|
||||
if (writingErrors)
|
||||
{
|
||||
string invalidNameStr = String.Join(',', invalidNames);
|
||||
string errorMsg = StringUtil.Format(Modules.InvalidExperimentalFeatureName, invalidNameStr);
|
||||
WriteError(new ErrorRecord(new ArgumentException(errorMsg),
|
||||
"Modules_InvalidExperimentalFeatureName",
|
||||
ErrorCategory.InvalidData, null));
|
||||
}
|
||||
|
||||
containedErrors = true;
|
||||
if (bailOnFirstError) { return null; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process all of the exports...
|
||||
@@ -2413,6 +2476,12 @@ namespace Microsoft.PowerShell.Commands
|
||||
manifestInfo.PowerShellVersion = powerShellVersion;
|
||||
manifestInfo.ProcessorArchitecture = requiredProcessorArchitecture;
|
||||
manifestInfo.Prefix = resolvedCommandPrefix;
|
||||
|
||||
if (expFeatureList != null)
|
||||
{
|
||||
manifestInfo.ExperimentalFeatures = new ReadOnlyCollection<ExperimentalFeature>(expFeatureList);
|
||||
}
|
||||
|
||||
if (assemblyList != null)
|
||||
{
|
||||
foreach (var a in assemblyList)
|
||||
@@ -3009,6 +3078,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
newManifestInfo.LicenseUri = manifestInfo.LicenseUri;
|
||||
newManifestInfo.IconUri = manifestInfo.IconUri;
|
||||
newManifestInfo.RepositorySourceLocation = manifestInfo.RepositorySourceLocation;
|
||||
newManifestInfo.ExperimentalFeatures = manifestInfo.ExperimentalFeatures;
|
||||
|
||||
// If we are in module discovery, then fix the path.
|
||||
if (ss == null)
|
||||
|
||||
@@ -301,49 +301,37 @@ namespace System.Management.Automation
|
||||
ProjectUri = null;
|
||||
IconUri = null;
|
||||
|
||||
var privateDataHashTable = _privateData as Hashtable;
|
||||
if (privateDataHashTable != null)
|
||||
if (_privateData is Hashtable hashData && hashData["PSData"] is Hashtable psData)
|
||||
{
|
||||
var psData = privateDataHashTable["PSData"] as Hashtable;
|
||||
if (psData != null)
|
||||
var tagsValue = psData["Tags"];
|
||||
if (tagsValue is object[] tags && tags.Length > 0)
|
||||
{
|
||||
object tagsValue = psData["Tags"];
|
||||
if (tagsValue != null)
|
||||
foreach (var tagString in tags.OfType<string>())
|
||||
{
|
||||
var tags = tagsValue as object[];
|
||||
if (tags != null && tags.Any())
|
||||
{
|
||||
foreach (var tagString in tags.OfType<string>())
|
||||
{
|
||||
AddToTags(tagString);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddToTags(tagsValue.ToString());
|
||||
}
|
||||
AddToTags(tagString);
|
||||
}
|
||||
|
||||
var licenseUri = psData["LicenseUri"] as string;
|
||||
if (licenseUri != null)
|
||||
{
|
||||
LicenseUri = GetUriFromString(licenseUri);
|
||||
}
|
||||
|
||||
var projectUri = psData["ProjectUri"] as string;
|
||||
if (projectUri != null)
|
||||
{
|
||||
ProjectUri = GetUriFromString(projectUri);
|
||||
}
|
||||
|
||||
var iconUri = psData["IconUri"] as string;
|
||||
if (iconUri != null)
|
||||
{
|
||||
IconUri = GetUriFromString(iconUri);
|
||||
}
|
||||
|
||||
ReleaseNotes = psData["ReleaseNotes"] as string;
|
||||
}
|
||||
else if (tagsValue is string tag)
|
||||
{
|
||||
AddToTags(tag);
|
||||
}
|
||||
|
||||
if (psData["LicenseUri"] is string licenseUri)
|
||||
{
|
||||
LicenseUri = GetUriFromString(licenseUri);
|
||||
}
|
||||
|
||||
if (psData["ProjectUri"] is string projectUri)
|
||||
{
|
||||
ProjectUri = GetUriFromString(projectUri);
|
||||
}
|
||||
|
||||
if (psData["IconUri"] is string iconUri)
|
||||
{
|
||||
IconUri = GetUriFromString(iconUri);
|
||||
}
|
||||
|
||||
ReleaseNotes = psData["ReleaseNotes"] as string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,6 +348,11 @@ namespace System.Management.Automation
|
||||
return uri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the experimental features declared in this module.
|
||||
/// </summary>
|
||||
public IEnumerable<ExperimentalFeature> ExperimentalFeatures { get; internal set; } = Utils.EmptyReadOnlyCollection<ExperimentalFeature>();
|
||||
|
||||
/// <summary>
|
||||
/// Tags of this module.
|
||||
/// </summary>
|
||||
|
||||
@@ -606,4 +606,10 @@
|
||||
<data name="PrerequisiteForDesktopEditionOnly" xml:space="preserve">
|
||||
<value>This prerequisite is valid for the PowerShell Desktop edition only.</value>
|
||||
</data>
|
||||
<data name="ExperimentalFeatureNameMissingOrEmpty" xml:space="preserve">
|
||||
<value>A non-empty string value should be specified for an experimental feature declared in the module manifest.</value>
|
||||
</data>
|
||||
<data name="InvalidExperimentalFeatureName" xml:space="preserve">
|
||||
<value>One or more invalid experimental feature names found: {0}. A module experimental feature name should follow this convention: 'ModuleName.FeatureName'.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
Reference in New Issue
Block a user