mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Refactor module version/GUID comparison logic (#7125)
This commit is contained in:
committed by
Aditya Patwardhan
parent
e888e51097
commit
5d06fba366
@@ -388,7 +388,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
PSModuleInfo alreadyLoadedModule = null;
|
||||
Context.Modules.ModuleTable.TryGetValue(module.Path, out alreadyLoadedModule);
|
||||
if (!BaseForce && IsModuleAlreadyLoaded(alreadyLoadedModule))
|
||||
if (!BaseForce && DoesAlreadyLoadedModuleSatisfyConstraints(alreadyLoadedModule))
|
||||
{
|
||||
AddModuleToModuleTables(this.Context, this.TargetSessionState.Internal, alreadyLoadedModule);
|
||||
|
||||
@@ -586,13 +586,8 @@ namespace Microsoft.PowerShell.Commands
|
||||
PSModuleInfo module;
|
||||
if (!BaseForce && Context.Modules.ModuleTable.TryGetValue(rootedPath, out module))
|
||||
{
|
||||
if (RequiredVersion == null
|
||||
|| module.Version.Equals(RequiredVersion)
|
||||
|| (BaseMinimumVersion == null && BaseMaximumVersion == null)
|
||||
|| module.ModuleType != ModuleType.Manifest
|
||||
|| (BaseMinimumVersion == null && BaseMaximumVersion != null && module.Version <= BaseMaximumVersion)
|
||||
|| (BaseMinimumVersion != null && BaseMaximumVersion == null && module.Version >= BaseMinimumVersion)
|
||||
|| (BaseMinimumVersion != null && BaseMaximumVersion != null && module.Version >= BaseMinimumVersion && module.Version <= BaseMaximumVersion))
|
||||
if (module.ModuleType != ModuleType.Manifest
|
||||
|| ModuleIntrinsics.IsVersionMatchingConstraints(module.Version, RequiredVersion, BaseMinimumVersion, BaseMaximumVersion))
|
||||
{
|
||||
alreadyLoaded = true;
|
||||
AddModuleToModuleTables(this.Context, this.TargetSessionState.Internal, module);
|
||||
|
||||
@@ -361,9 +361,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
foreach (var version in ModuleUtils.GetModuleVersionSubfolders(moduleBase))
|
||||
{
|
||||
// Skip the version folder if it is not equal to the required version or does not satisfy the minimum/maximum version criteria
|
||||
if ((BaseRequiredVersion != null && !BaseRequiredVersion.Equals(version))
|
||||
|| (BaseMinimumVersion != null && BaseRequiredVersion == null && version < BaseMinimumVersion)
|
||||
|| (BaseMaximumVersion != null && BaseRequiredVersion == null && version > BaseMaximumVersion))
|
||||
if (!ModuleIntrinsics.IsVersionMatchingConstraints(version, BaseRequiredVersion, BaseMinimumVersion, BaseMaximumVersion))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1585,22 +1583,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
}
|
||||
|
||||
// TODO/FIXME: use IsModuleAlreadyLoaded to get consistent behavior
|
||||
// if (IsModuleAlreadyLoaded(loadedModule) &&
|
||||
// ((manifestProcessingFlags & ManifestProcessingFlags.LoadElements) == ManifestProcessingFlags.LoadElements))
|
||||
if (loadedModule != null &&
|
||||
(BaseRequiredVersion == null || loadedModule.Version.Equals(BaseRequiredVersion)) &&
|
||||
((BaseMinimumVersion == null && BaseMaximumVersion == null)
|
||||
||
|
||||
(BaseMaximumVersion != null && BaseMinimumVersion == null &&
|
||||
loadedModule.Version <= BaseMaximumVersion)
|
||||
||
|
||||
(BaseMaximumVersion == null && BaseMinimumVersion != null &&
|
||||
loadedModule.Version >= BaseMinimumVersion)
|
||||
||
|
||||
(BaseMaximumVersion != null && BaseMinimumVersion != null &&
|
||||
loadedModule.Version >= BaseMinimumVersion && loadedModule.Version <= BaseMaximumVersion)) &&
|
||||
(BaseGuid == null || loadedModule.Guid.Equals(BaseGuid)) && importingModule)
|
||||
if (importingModule && DoesAlreadyLoadedModuleSatisfyConstraints(loadedModule))
|
||||
{
|
||||
if (!BaseForce)
|
||||
{
|
||||
@@ -1672,23 +1655,20 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
if (bailOnFirstError) return null;
|
||||
}
|
||||
else if (requiredVersion != null && !moduleVersion.Equals(requiredVersion))
|
||||
else if (!ModuleIntrinsics.AreModuleFieldsMatchingConstraints(
|
||||
moduleGuid: manifestGuid,
|
||||
moduleVersion: moduleVersion,
|
||||
requiredGuid: requiredModuleGuid,
|
||||
requiredVersion: requiredVersion,
|
||||
minimumRequiredVersion: minimumVersion,
|
||||
maximumRequiredVersion: maximumVersion))
|
||||
{
|
||||
if (bailOnFirstError) return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (moduleVersion < minimumVersion || (maximumVersion != null && moduleVersion > maximumVersion))
|
||||
if (bailOnFirstError)
|
||||
{
|
||||
if (bailOnFirstError) return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (requiredModuleGuid != null && !requiredModuleGuid.Equals(manifestGuid))
|
||||
{
|
||||
if (bailOnFirstError) return null;
|
||||
}
|
||||
|
||||
// Verify that the module version from the module manifest is equal to module version folder.
|
||||
DirectoryInfo parent = null;
|
||||
try
|
||||
@@ -3644,91 +3624,27 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// </summary>
|
||||
/// <param name="context">Execution Context.</param>
|
||||
/// <param name="requiredModule">Either a string or a hash of ModuleName, optional Guid, and ModuleVersion.</param>
|
||||
/// <param name="wrongVersion">Sets if the module cannot be found due to incorrect version.</param>
|
||||
/// <param name="wrongGuid">Sets if the module cannot be found due to incorrect guid.</param>
|
||||
/// <param name="matchFailureReason">The reason the module failed to load, or null on success.</param>
|
||||
/// <param name="loaded">Sets if the module/snapin is already present.</param>
|
||||
/// <returns>null if the module is not loaded or loadElements is false, the loaded module otherwise.</returns>
|
||||
internal static object IsModuleLoaded(ExecutionContext context, ModuleSpecification requiredModule, out bool wrongVersion, out bool wrongGuid, out bool loaded)
|
||||
internal static object IsModuleLoaded(ExecutionContext context, ModuleSpecification requiredModule, out ModuleMatchFailure matchFailureReason, out bool loaded)
|
||||
{
|
||||
loaded = false;
|
||||
Dbg.Assert(requiredModule != null, "Caller should verify requiredModuleSpecification != null");
|
||||
|
||||
// Assume the module is not loaded.
|
||||
object result = null;
|
||||
wrongVersion = false;
|
||||
wrongGuid = false;
|
||||
|
||||
string moduleName = requiredModule.Name;
|
||||
Guid? moduleGuid = requiredModule.Guid;
|
||||
|
||||
Dbg.Assert(moduleName != null, "GetModuleSpecification should guarantee that moduleName != null");
|
||||
Dbg.Assert(requiredModule.Name != null, "GetModuleSpecification should guarantee that moduleName != null");
|
||||
ModuleMatchFailure matchFailure = ModuleMatchFailure.None;
|
||||
foreach (PSModuleInfo module in context.Modules.GetModules(new string[] { "*" }, false))
|
||||
{
|
||||
if (moduleName.Equals(module.Name, StringComparison.OrdinalIgnoreCase))
|
||||
// Check that the module meets the module constraints give
|
||||
if (ModuleIntrinsics.IsModuleMatchingModuleSpec(out matchFailure, module, requiredModule))
|
||||
{
|
||||
if (!moduleGuid.HasValue || moduleGuid.Value.Equals(module.Guid))
|
||||
{
|
||||
if (requiredModule.RequiredVersion != null)
|
||||
{
|
||||
if (requiredModule.RequiredVersion.Equals(module.Version))
|
||||
{
|
||||
result = module;
|
||||
loaded = true;
|
||||
break;
|
||||
}
|
||||
|
||||
wrongVersion = true;
|
||||
}
|
||||
else if (requiredModule.Version != null)
|
||||
{
|
||||
if (requiredModule.MaximumVersion != null)
|
||||
{
|
||||
if (GetMaximumVersion(requiredModule.MaximumVersion) >= module.Version && requiredModule.Version <= module.Version)
|
||||
{
|
||||
result = module;
|
||||
loaded = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
wrongVersion = true;
|
||||
}
|
||||
}
|
||||
else if (requiredModule.Version <= module.Version)
|
||||
{
|
||||
result = module;
|
||||
loaded = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
wrongVersion = true;
|
||||
}
|
||||
}
|
||||
else if (requiredModule.MaximumVersion != null)
|
||||
{
|
||||
if (GetMaximumVersion(requiredModule.MaximumVersion) >= module.Version)
|
||||
{
|
||||
result = module;
|
||||
loaded = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
wrongVersion = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = module;
|
||||
loaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wrongGuid = true;
|
||||
}
|
||||
result = module;
|
||||
loaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3742,6 +3658,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
}
|
||||
|
||||
matchFailureReason = matchFailure;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -3795,10 +3712,9 @@ namespace Microsoft.PowerShell.Commands
|
||||
Guid? moduleGuid = requiredModuleSpecification.Guid;
|
||||
PSModuleInfo result = null;
|
||||
|
||||
bool wrongVersion = false;
|
||||
bool wrongGuid = false;
|
||||
ModuleMatchFailure loadFailureReason = ModuleMatchFailure.None;
|
||||
bool loaded = false;
|
||||
object loadedModule = IsModuleLoaded(context, requiredModuleSpecification, out wrongVersion, out wrongGuid, out loaded);
|
||||
object loadedModule = IsModuleLoaded(context, requiredModuleSpecification, out loadFailureReason, out loaded);
|
||||
|
||||
if (loadedModule == null)
|
||||
{
|
||||
@@ -3855,33 +3771,73 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
if (0 != (manifestProcessingFlags & ManifestProcessingFlags.WriteErrors))
|
||||
{
|
||||
if (wrongVersion)
|
||||
switch (loadFailureReason)
|
||||
{
|
||||
if (requiredModuleSpecification.RequiredVersion != null)
|
||||
{
|
||||
message = StringUtil.Format(Modules.RequiredModuleNotLoadedWrongVersion, moduleManifestPath, moduleName, requiredModuleSpecification.RequiredVersion);
|
||||
}
|
||||
else if (requiredModuleSpecification.Version != null && requiredModuleSpecification.MaximumVersion == null)
|
||||
{
|
||||
message = StringUtil.Format(Modules.RequiredModuleNotLoadedWrongVersion, moduleManifestPath, moduleName, requiredModuleSpecification.Version);
|
||||
}
|
||||
else if (requiredModuleSpecification.Version == null && requiredModuleSpecification.MaximumVersion != null)
|
||||
{
|
||||
message = StringUtil.Format(Modules.RequiredModuleNotLoadedWrongMaximumVersion, moduleManifestPath, moduleName, requiredModuleSpecification.MaximumVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
message = StringUtil.Format(Modules.RequiredModuleNotLoadedWrongMinimumVersionAndMaximumVersion, moduleManifestPath, moduleName, requiredModuleSpecification.Version, requiredModuleSpecification.MaximumVersion);
|
||||
}
|
||||
}
|
||||
else if (wrongGuid)
|
||||
{
|
||||
message = StringUtil.Format(Modules.RequiredModuleNotLoadedWrongGuid, moduleManifestPath, moduleName, moduleGuid.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
message = StringUtil.Format(Modules.RequiredModuleNotLoaded, moduleManifestPath, moduleName);
|
||||
case ModuleMatchFailure.RequiredVersion:
|
||||
message = StringUtil.Format(
|
||||
Modules.RequiredModuleNotLoadedWrongVersion,
|
||||
moduleManifestPath,
|
||||
moduleName,
|
||||
requiredModuleSpecification.RequiredVersion);
|
||||
break;
|
||||
|
||||
case ModuleMatchFailure.MinimumVersion:
|
||||
// If both max and min versions were specified, use a different error message
|
||||
if (requiredModuleSpecification.MaximumVersion == null)
|
||||
{
|
||||
message = StringUtil.Format(
|
||||
Modules.RequiredModuleNotLoadedWrongVersion,
|
||||
moduleManifestPath, moduleName,
|
||||
requiredModuleSpecification.Version);
|
||||
}
|
||||
else
|
||||
{
|
||||
message = StringUtil.Format(
|
||||
Modules.RequiredModuleNotLoadedWrongMinimumVersionAndMaximumVersion,
|
||||
moduleManifestPath,
|
||||
moduleName,
|
||||
requiredModuleSpecification.Version,
|
||||
requiredModuleSpecification.MaximumVersion);
|
||||
}
|
||||
break;
|
||||
|
||||
case ModuleMatchFailure.MaximumVersion:
|
||||
// If both max and min versions were specified, use a different error message
|
||||
if (requiredModuleSpecification.Version == null)
|
||||
{
|
||||
message = StringUtil.Format(
|
||||
Modules.RequiredModuleNotLoadedWrongMaximumVersion,
|
||||
moduleManifestPath,
|
||||
moduleName,
|
||||
requiredModuleSpecification.MaximumVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
message = StringUtil.Format(
|
||||
Modules.RequiredModuleNotLoadedWrongMinimumVersionAndMaximumVersion,
|
||||
moduleManifestPath,
|
||||
moduleName,
|
||||
requiredModuleSpecification.Version,
|
||||
requiredModuleSpecification.MaximumVersion);
|
||||
}
|
||||
break;
|
||||
|
||||
case ModuleMatchFailure.Guid:
|
||||
message = StringUtil.Format(
|
||||
Modules.RequiredModuleNotLoadedWrongGuid,
|
||||
moduleManifestPath,
|
||||
moduleName,
|
||||
moduleGuid.Value);
|
||||
break;
|
||||
|
||||
default:
|
||||
message = StringUtil.Format(
|
||||
Modules.RequiredModuleNotLoaded,
|
||||
moduleManifestPath,
|
||||
moduleName);
|
||||
break;
|
||||
}
|
||||
|
||||
MissingMemberException mm = new MissingMemberException(message);
|
||||
error = new ErrorRecord(mm, "Modules_InvalidManifest",
|
||||
ErrorCategory.ResourceUnavailable, moduleManifestPath);
|
||||
@@ -3943,8 +3899,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
else
|
||||
{
|
||||
bool wrongVersion = false;
|
||||
bool wrongGuid = false;
|
||||
// Check if the correct module is loaded using Version , Guid Information.
|
||||
string moduleNameToCheckAgainst = requiredModule.Name;
|
||||
string manifestPath = string.Empty;
|
||||
@@ -3953,6 +3907,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
manifestPath = moduleNameToCheckAgainst;
|
||||
moduleNameToCheckAgainst = Path.GetFileNameWithoutExtension(moduleNameToCheckAgainst);
|
||||
}
|
||||
|
||||
ModuleSpecification ms = new ModuleSpecification(moduleNameToCheckAgainst);
|
||||
if (requiredModule.Guid != null)
|
||||
{
|
||||
@@ -3970,9 +3925,13 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
ms.MaximumVersion = requiredModule.MaximumVersion;
|
||||
}
|
||||
|
||||
ModuleMatchFailure loadFailureReason;
|
||||
bool loaded = false;
|
||||
object r = IsModuleLoaded(context, ms, out wrongVersion, out wrongGuid, out loaded);
|
||||
object r = IsModuleLoaded(context, ms, out loadFailureReason, out loaded);
|
||||
|
||||
Dbg.Assert(r is PSModuleInfo, "The returned value should be PSModuleInfo");
|
||||
|
||||
result = r as PSModuleInfo;
|
||||
if (result == null)
|
||||
{
|
||||
@@ -4099,43 +4058,13 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
tempResult = powerShell.Invoke<PSModuleInfo>();
|
||||
}
|
||||
|
||||
// Check if the available module is of the correct version and GUID
|
||||
foreach (var m in tempResult)
|
||||
foreach (var module in tempResult)
|
||||
{
|
||||
if (!requiredModule.Guid.HasValue || requiredModule.Guid.Value.Equals(m.Guid))
|
||||
if (ModuleIntrinsics.IsModuleMatchingModuleSpec(module, requiredModule))
|
||||
{
|
||||
if (requiredModule.RequiredVersion != null)
|
||||
{
|
||||
if (requiredModule.RequiredVersion.Equals(m.Version))
|
||||
{
|
||||
result.Add(m);
|
||||
}
|
||||
}
|
||||
else if (requiredModule.Version != null)
|
||||
{
|
||||
if (requiredModule.MaximumVersion != null)
|
||||
{
|
||||
if (GetMaximumVersion(requiredModule.MaximumVersion) >= m.Version && requiredModule.Version <= m.Version)
|
||||
{
|
||||
result.Add(m);
|
||||
}
|
||||
}
|
||||
else if (requiredModule.Version <= m.Version)
|
||||
{
|
||||
result.Add(m);
|
||||
}
|
||||
}
|
||||
else if (requiredModule.MaximumVersion != null)
|
||||
{
|
||||
if (GetMaximumVersion(requiredModule.MaximumVersion) >= m.Version)
|
||||
{
|
||||
result.Add(m);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(m);
|
||||
}
|
||||
result.Add(module);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -5074,34 +5003,19 @@ namespace Microsoft.PowerShell.Commands
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool IsModuleAlreadyLoaded(PSModuleInfo alreadyLoadedModule)
|
||||
/// <summary>
|
||||
/// Checks if an already loaded module meets the constraints passed to the module cmdlet by the user.
|
||||
/// </summary>
|
||||
/// <param name="alreadyLoadedModule">The already loaded module that matched the name of the module to load.</param>
|
||||
/// <returns>True if the pre-loaded module matches all GUID and version constraints provided, false otherwise.</returns>
|
||||
internal bool DoesAlreadyLoadedModuleSatisfyConstraints(PSModuleInfo alreadyLoadedModule)
|
||||
{
|
||||
if (alreadyLoadedModule == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.BaseRequiredVersion != null && !alreadyLoadedModule.Version.Equals(this.BaseRequiredVersion))
|
||||
{
|
||||
// "alreadyLoadedModule" is a different module (than the one we want to load)
|
||||
return false;
|
||||
}
|
||||
if (this.BaseMinimumVersion != null && alreadyLoadedModule.Version < this.BaseMinimumVersion)
|
||||
{
|
||||
// "alreadyLoadedModule" is a different module (than the one we want to load)
|
||||
return false;
|
||||
}
|
||||
if (this.BaseMaximumVersion != null && alreadyLoadedModule.Version > this.BaseMaximumVersion)
|
||||
{
|
||||
// "alreadyLoadedModule" is a different module (than the one we want to load)
|
||||
return false;
|
||||
}
|
||||
if (BaseGuid != null && !alreadyLoadedModule.Guid.Equals(this.BaseGuid))
|
||||
{
|
||||
// "alreadyLoadedModule" is a different module (than the one we want to load)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return ModuleIntrinsics.IsModuleMatchingConstraints(
|
||||
alreadyLoadedModule,
|
||||
guid: BaseGuid,
|
||||
requiredVersion: BaseRequiredVersion,
|
||||
minimumVersion: BaseMinimumVersion,
|
||||
maximumVersion: BaseMaximumVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -5118,7 +5032,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
PSModuleInfo alreadyLoadedModule;
|
||||
if (this.Context.Modules.ModuleTable.TryGetValue(modulePath, out alreadyLoadedModule))
|
||||
{
|
||||
if (this.IsModuleAlreadyLoaded(alreadyLoadedModule))
|
||||
if (this.DoesAlreadyLoadedModuleSatisfyConstraints(alreadyLoadedModule))
|
||||
{
|
||||
if (this.BaseForce) // remove the previously imported module + return null (null = please proceed with regular import)
|
||||
{
|
||||
@@ -5256,17 +5170,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
// If the module has already been loaded, just emit it and continue...
|
||||
Context.Modules.ModuleTable.TryGetValue(fileName, out module);
|
||||
// TODO/FIXME: use IsModuleAlreadyLoaded to get consistent behavior
|
||||
// if (!BaseForce &&
|
||||
// IsModuleAlreadyLoaded(module) &&
|
||||
// ((manifestProcessingFlags & ManifestProcessingFlags.LoadElements) == ManifestProcessingFlags.LoadElements))
|
||||
if (!BaseForce && module != null &&
|
||||
(BaseRequiredVersion == null || module.Version.Equals(BaseRequiredVersion)) &&
|
||||
((BaseMinimumVersion == null && BaseMaximumVersion == null)
|
||||
|| (BaseMaximumVersion != null && BaseMinimumVersion == null && module.Version <= BaseMaximumVersion)
|
||||
|| (BaseMaximumVersion == null && BaseMinimumVersion != null && module.Version >= BaseMinimumVersion)
|
||||
|| (BaseMaximumVersion != null && BaseMinimumVersion != null && module.Version >= BaseMinimumVersion && module.Version <= BaseMaximumVersion)) &&
|
||||
(BaseGuid == null || module.Guid.Equals(BaseGuid)) && importingModule)
|
||||
if (!BaseForce && importingModule && DoesAlreadyLoadedModuleSatisfyConstraints(module))
|
||||
{
|
||||
moduleFileFound = true;
|
||||
module = Context.Modules.ModuleTable[fileName];
|
||||
@@ -5311,12 +5215,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
moduleFileFound = true;
|
||||
// Win8: 325243 - Added the version check so that we do not unload modules with the same name but different version
|
||||
if (BaseForce && module != null &&
|
||||
(this.BaseRequiredVersion == null || module.Version.Equals(this.BaseRequiredVersion)) &&
|
||||
(BaseGuid == null || module.Guid.Equals(BaseGuid)))
|
||||
// TODO/FIXME: use IsModuleAlreadyLoaded to get consistent behavior
|
||||
// TODO/FIXME: (for example the checks above are not lookint at this.BaseMinimumVersion)
|
||||
// if (BaseForce && IsModuleAlreadyLoaded(module))
|
||||
if (BaseForce && DoesAlreadyLoadedModuleSatisfyConstraints(module))
|
||||
{
|
||||
RemoveModule(module);
|
||||
}
|
||||
@@ -5493,14 +5392,11 @@ namespace Microsoft.PowerShell.Commands
|
||||
// This will allow the search to continue and load a different version of the module.
|
||||
if (Context.Modules.ModuleTable.TryGetValue(fileName, out module))
|
||||
{
|
||||
if (BaseMinimumVersion != null && module.Version >= BaseMinimumVersion)
|
||||
if (!ModuleIntrinsics.IsVersionMatchingConstraints(module.Version, minimumVersion: BaseMinimumVersion, maximumVersion: BaseMaximumVersion))
|
||||
{
|
||||
if (BaseMaximumVersion == null || module.Version <= BaseMaximumVersion)
|
||||
{
|
||||
found = false;
|
||||
moduleFileFound = false;
|
||||
return null;
|
||||
}
|
||||
found = false;
|
||||
moduleFileFound = false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,21 +410,253 @@ namespace System.Management.Automation
|
||||
return modulesMatched.OrderBy(m => m.Name).ToList();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Check if a given module info object matches a given module specification.
|
||||
/// </summary>
|
||||
/// <param name="moduleInfo">The module info object to check.</param>
|
||||
/// <param name="moduleSpec">The module specification to match the module info object against.</param>
|
||||
/// <returns>True if the module info object meets all the constraints on the module specification, false otherwise.</returns>
|
||||
internal static bool IsModuleMatchingModuleSpec(PSModuleInfo moduleInfo, ModuleSpecification moduleSpec)
|
||||
{
|
||||
if (moduleInfo != null && moduleSpec != null &&
|
||||
moduleInfo.Name.Equals(moduleSpec.Name, StringComparison.OrdinalIgnoreCase) &&
|
||||
(!moduleSpec.Guid.HasValue || moduleSpec.Guid.Equals(moduleInfo.Guid)) &&
|
||||
((moduleSpec.Version == null && moduleSpec.RequiredVersion == null && moduleSpec.MaximumVersion == null)
|
||||
|| (moduleSpec.RequiredVersion != null && moduleSpec.RequiredVersion.Equals(moduleInfo.Version))
|
||||
|| (moduleSpec.MaximumVersion == null && moduleSpec.Version != null && moduleSpec.RequiredVersion == null && moduleSpec.Version <= moduleInfo.Version)
|
||||
|| (moduleSpec.MaximumVersion != null && moduleSpec.Version == null && moduleSpec.RequiredVersion == null && ModuleCmdletBase.GetMaximumVersion(moduleSpec.MaximumVersion) >= moduleInfo.Version)
|
||||
|| (moduleSpec.MaximumVersion != null && moduleSpec.Version != null && moduleSpec.RequiredVersion == null && ModuleCmdletBase.GetMaximumVersion(moduleSpec.MaximumVersion) >= moduleInfo.Version && moduleSpec.Version <= moduleInfo.Version)))
|
||||
return IsModuleMatchingModuleSpec(out ModuleMatchFailure matchFailureReason, moduleInfo, moduleSpec);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a given module info object matches a given module specification.
|
||||
/// </summary>
|
||||
/// <param name="matchFailureReason">The constraint that caused the match failure, if any.</param>
|
||||
/// <param name="moduleInfo">The module info object to check.</param>
|
||||
/// <param name="moduleSpec">The module specification to match the module info object against.</param>
|
||||
/// <returns>True if the module info object meets all the constraints on the module specification, false otherwise.</returns>
|
||||
internal static bool IsModuleMatchingModuleSpec(out ModuleMatchFailure matchFailureReason, PSModuleInfo moduleInfo, ModuleSpecification moduleSpec)
|
||||
{
|
||||
if (moduleSpec == null)
|
||||
{
|
||||
return true;
|
||||
matchFailureReason = ModuleMatchFailure.NullModuleSpecification;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return IsModuleMatchingConstraints(
|
||||
out matchFailureReason,
|
||||
moduleInfo,
|
||||
moduleSpec.Name,
|
||||
moduleSpec.Guid,
|
||||
moduleSpec.RequiredVersion,
|
||||
moduleSpec.Version,
|
||||
moduleSpec.MaximumVersion == null ? null : ModuleCmdletBase.GetMaximumVersion(moduleSpec.MaximumVersion));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a given module info object matches the given constraints.
|
||||
/// Constraints given as null are ignored.
|
||||
/// </summary>
|
||||
/// <param name="moduleInfo">The module info object to check.</param>
|
||||
/// <param name="name">The name of the expected module.</param>
|
||||
/// <param name="guid">The guid of the expected module.</param>
|
||||
/// <param name="requiredVersion">The required version of the expected module.</param>
|
||||
/// <param name="minimumVersion">The minimum required version of the expected module.</param>
|
||||
/// <param name="maximumVersion">The maximum required version of the expected module.</param>
|
||||
/// <returns>True if the module info object matches all given constraints, false otherwise.</returns>
|
||||
internal static bool IsModuleMatchingConstraints(
|
||||
PSModuleInfo moduleInfo,
|
||||
string name = null,
|
||||
Guid? guid = null,
|
||||
Version requiredVersion = null,
|
||||
Version minimumVersion = null,
|
||||
Version maximumVersion = null)
|
||||
{
|
||||
return IsModuleMatchingConstraints(
|
||||
out ModuleMatchFailure matchFailureReason,
|
||||
moduleInfo,
|
||||
name,
|
||||
guid,
|
||||
requiredVersion,
|
||||
minimumVersion,
|
||||
maximumVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a given module info object matches the given constraints.
|
||||
/// Constraints given as null are ignored.
|
||||
/// </summary>
|
||||
/// <param name="matchFailureReason">The reason for the module constraint match failing.</param>
|
||||
/// <param name="moduleInfo">The module info object to check.</param>
|
||||
/// <param name="name">The name of the expected module.</param>
|
||||
/// <param name="guid">The guid of the expected module.</param>
|
||||
/// <param name="requiredVersion">The required version of the expected module.</param>
|
||||
/// <param name="minimumVersion">The minimum required version of the expected module.</param>
|
||||
/// <param name="maximumVersion">The maximum required version of the expected module.</param>
|
||||
/// <returns>True if the module info object matches all given constraints, false otherwise.</returns>
|
||||
internal static bool IsModuleMatchingConstraints(
|
||||
out ModuleMatchFailure matchFailureReason,
|
||||
PSModuleInfo moduleInfo,
|
||||
string name,
|
||||
Guid? guid,
|
||||
Version requiredVersion,
|
||||
Version minimumVersion,
|
||||
Version maximumVersion)
|
||||
{
|
||||
// Define that a null module does not meet any constraints
|
||||
if (moduleInfo == null)
|
||||
{
|
||||
matchFailureReason = ModuleMatchFailure.NullModule;
|
||||
return false;
|
||||
}
|
||||
|
||||
return AreModuleFieldsMatchingConstraints(
|
||||
out matchFailureReason,
|
||||
moduleInfo.Name,
|
||||
moduleInfo.Guid,
|
||||
moduleInfo.Version,
|
||||
name,
|
||||
guid,
|
||||
requiredVersion,
|
||||
minimumVersion,
|
||||
maximumVersion
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that given module fields meet any given constraints.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The name of the module to check.</param>
|
||||
/// <param name="moduleGuid">The GUID of the module to check.</param>
|
||||
/// <param name="moduleVersion">The version of the module to check.</param>
|
||||
/// <param name="requiredName">The name the module must have, if any.</param>
|
||||
/// <param name="requiredGuid">The GUID the module must have, if any.</param>
|
||||
/// <param name="requiredVersion">The exact version the module must have, if any.</param>
|
||||
/// <param name="minimumRequiredVersion">The minimum version the module may have, if any.</param>
|
||||
/// <param name="maximumRequiredVersion">The maximum version the module may have, if any.</param>
|
||||
/// <returns>True if the module parameters match all given constraints, false otherwise.</returns>
|
||||
internal static bool AreModuleFieldsMatchingConstraints(
|
||||
string moduleName = null,
|
||||
Guid? moduleGuid = null,
|
||||
Version moduleVersion = null,
|
||||
string requiredName = null,
|
||||
Guid? requiredGuid = null,
|
||||
Version requiredVersion = null,
|
||||
Version minimumRequiredVersion = null,
|
||||
Version maximumRequiredVersion = null)
|
||||
{
|
||||
return AreModuleFieldsMatchingConstraints(
|
||||
out ModuleMatchFailure matchFailureReason,
|
||||
moduleName,
|
||||
moduleGuid,
|
||||
moduleVersion,
|
||||
requiredName,
|
||||
requiredGuid,
|
||||
requiredVersion,
|
||||
minimumRequiredVersion,
|
||||
maximumRequiredVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that given module fields meet any given constraints.
|
||||
/// </summary>
|
||||
/// <param name="matchFailureReason">The reason the match failed, if any.</param>
|
||||
/// <param name="moduleName">The name of the module to check.</param>
|
||||
/// <param name="moduleGuid">The GUID of the module to check.</param>
|
||||
/// <param name="moduleVersion">The version of the module to check.</param>
|
||||
/// <param name="requiredName">The name the module must have, if any.</param>
|
||||
/// <param name="requiredGuid">The GUID the module must have, if any.</param>
|
||||
/// <param name="requiredVersion">The exact version the module must have, if any.</param>
|
||||
/// <param name="minimumRequiredVersion">The minimum version the module may have, if any.</param>
|
||||
/// <param name="maximumRequiredVersion">The maximum version the module may have, if any.</param>
|
||||
/// <returns>True if the module parameters match all given constraints, false otherwise.</returns>
|
||||
internal static bool AreModuleFieldsMatchingConstraints(
|
||||
out ModuleMatchFailure matchFailureReason,
|
||||
string moduleName,
|
||||
Guid? moduleGuid,
|
||||
Version moduleVersion,
|
||||
string requiredName,
|
||||
Guid? requiredGuid,
|
||||
Version requiredVersion,
|
||||
Version minimumRequiredVersion,
|
||||
Version maximumRequiredVersion)
|
||||
{
|
||||
// If a name is required, check it matches
|
||||
if (requiredName != null && !requiredName.Equals(moduleName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
matchFailureReason = ModuleMatchFailure.Name;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a GUID is required, check it matches
|
||||
if (requiredGuid != null && !requiredGuid.Equals(moduleGuid))
|
||||
{
|
||||
matchFailureReason = ModuleMatchFailure.Guid;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the versions
|
||||
return IsVersionMatchingConstraints(out matchFailureReason, moduleVersion, requiredVersion, minimumRequiredVersion, maximumRequiredVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that a given module version matches the required or minimum/maximum version constraints.
|
||||
/// Null constraints are not checked.
|
||||
/// </summary>
|
||||
/// <param name="version">The module version to check. Must not be null</param>
|
||||
/// <param name="requiredVersion">The version that the given version must be, if not null.</param>
|
||||
/// <param name="minimumVersion">The minimum version that the given version must be greater than or equal to, if not null.</param>
|
||||
/// <param name="maximumVersion">The maximum version that the given version must be less then or equal to, if not null.</param>
|
||||
/// <returns>
|
||||
/// True if the version matches the required version, or if it is absent, is between the minimum and maximum versions, and false otherwise.
|
||||
/// </returns>
|
||||
internal static bool IsVersionMatchingConstraints(
|
||||
Version version,
|
||||
Version requiredVersion = null,
|
||||
Version minimumVersion = null,
|
||||
Version maximumVersion = null)
|
||||
{
|
||||
return IsVersionMatchingConstraints(out ModuleMatchFailure matchFailureReason, version, requiredVersion, minimumVersion, maximumVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that a given module version matches the required or minimum/maximum version constraints.
|
||||
/// Null constraints are not checked.
|
||||
/// </summary>
|
||||
/// <param name="matchFailureReason">The reason why the match failed.</param>
|
||||
/// <param name="version">The module version to check. Must not be null</param>
|
||||
/// <param name="requiredVersion">The version that the given version must be, if not null.</param>
|
||||
/// <param name="minimumVersion">The minimum version that the given version must be greater than or equal to, if not null.</param>
|
||||
/// <param name="maximumVersion">The maximum version that the given version must be less then or equal to, if not null.</param>
|
||||
/// <returns>
|
||||
/// True if the version matches the required version, or if it is absent, is between the minimum and maximum versions, and false otherwise.
|
||||
/// </returns>
|
||||
internal static bool IsVersionMatchingConstraints(
|
||||
out ModuleMatchFailure matchFailureReason,
|
||||
Version version,
|
||||
Version requiredVersion = null,
|
||||
Version minimumVersion = null,
|
||||
Version maximumVersion = null)
|
||||
{
|
||||
Dbg.Assert(version != null, $"Caller to verify that {nameof(version)} is not null");
|
||||
|
||||
// If a RequiredVersion is given it overrides other version settings
|
||||
if (requiredVersion != null)
|
||||
{
|
||||
matchFailureReason = ModuleMatchFailure.RequiredVersion;
|
||||
return requiredVersion.Equals(version);
|
||||
}
|
||||
|
||||
// Check the version is at least the minimum version
|
||||
if (minimumVersion != null && version < minimumVersion)
|
||||
{
|
||||
matchFailureReason = ModuleMatchFailure.MinimumVersion;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the version is at most the maximum version
|
||||
if (maximumVersion != null && version > maximumVersion)
|
||||
{
|
||||
matchFailureReason = ModuleMatchFailure.MaximumVersion;
|
||||
return false;
|
||||
}
|
||||
|
||||
matchFailureReason = ModuleMatchFailure.None;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static Version GetManifestModuleVersion(string manifestPath)
|
||||
@@ -1306,6 +1538,36 @@ namespace System.Management.Automation
|
||||
}
|
||||
} // ModuleIntrinsics
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration of reasons for a failure to match a module by constraints.
|
||||
/// </summary>
|
||||
internal enum ModuleMatchFailure
|
||||
{
|
||||
/// <summary>Match did not fail.</summary>
|
||||
None,
|
||||
|
||||
/// <summary>Match failed because the module was null.</summary>
|
||||
NullModule,
|
||||
|
||||
/// <summary>Module name did not match.</summary>
|
||||
Name,
|
||||
|
||||
/// <summary>Module GUID did not match.</summary>
|
||||
Guid,
|
||||
|
||||
/// <summary>Module version did not match the required version.</summary>
|
||||
RequiredVersion,
|
||||
|
||||
/// <summary>Module version was lower than the minimum version.</summary>
|
||||
MinimumVersion,
|
||||
|
||||
/// <summary>Module version was greater than the maximum version.</summary>
|
||||
MaximumVersion,
|
||||
|
||||
/// <summary>The module specifcation passed in was null.</summary>
|
||||
NullModuleSpecification,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by Modules/Snapins to provide a hook to the engine for startup initialization
|
||||
/// w.r.t compiled assembly loading.
|
||||
|
||||
@@ -865,7 +865,7 @@ Describe "Preloaded module specification checking" -Tags "Feature" {
|
||||
{ Import-Module -FullyQualifiedName $modSpec -ErrorAction Stop } | Should -Throw -ErrorId 'Modules_ModuleWithVersionNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand'
|
||||
}
|
||||
|
||||
It "Does not load the module with FullyQualifiedName from the manifest when ModuleVersion=<ModuleVersion>, MaximumVersion=<MaximumVersion>, RequiredVersion=<RequiredVersion>, Guid=<Guid>" -TestCases $guidFailCases -Pending {
|
||||
It "Does not load the module with FullyQualifiedName from the manifest when ModuleVersion=<ModuleVersion>, MaximumVersion=<MaximumVersion>, RequiredVersion=<RequiredVersion>, Guid=<Guid>" -TestCases $guidFailCases {
|
||||
param($ModuleVersion, $MaximumVersion, $RequiredVersion, $Guid)
|
||||
|
||||
$modSpec = New-ModuleSpecification -ModuleName $manifestPath -ModuleVersion $ModuleVersion -MaximumVersion $MaximumVersion -RequiredVersion $RequiredVersion -Guid $Guid
|
||||
@@ -1088,7 +1088,7 @@ Describe "Preloaded modules with versioned directory version checking" -Tag "Fea
|
||||
{ Import-Module -FullyQualifiedName $modSpec -ErrorAction Stop } | Should -Throw -ErrorId 'Modules_ModuleWithVersionNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand'
|
||||
}
|
||||
|
||||
It "Does not load the module with FullyQualifiedName from the manifest when ModuleVersion=<ModuleVersion>, MaximumVersion=<MaximumVersion>, RequiredVersion=<RequiredVersion>, Guid=<Guid>" -TestCases $guidFailCases -Pending {
|
||||
It "Does not load the module with FullyQualifiedName from the manifest when ModuleVersion=<ModuleVersion>, MaximumVersion=<MaximumVersion>, RequiredVersion=<RequiredVersion>, Guid=<Guid>" -TestCases $guidFailCases {
|
||||
param($ModuleVersion, $MaximumVersion, $RequiredVersion, $Guid)
|
||||
|
||||
$modSpec = New-ModuleSpecification -ModuleName $manifestPath -ModuleVersion $ModuleVersion -MaximumVersion $MaximumVersion -RequiredVersion $RequiredVersion -Guid $Guid
|
||||
|
||||
Reference in New Issue
Block a user