Skip to content

Commit ac12de5

Browse files
author
Kapil Borle
committed
Use PowerShellVersion from module manifest
1 parent 5b94fb7 commit ac12de5

File tree

1 file changed

+84
-32
lines changed

1 file changed

+84
-32
lines changed

Engine/Helper.cs

Lines changed: 84 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,10 @@ public static IEnumerable<string> GetModuleManifestKeys(Version powershellVersio
16131613
{
16141614
throw new ArgumentNullException("powershellVersion");
16151615
}
1616+
if (!IsPowerShellVersionSupported(powershellVersion))
1617+
{
1618+
throw new ArgumentException("Invalid PowerShell version. Choose from 3.0, 4.0 or 5.0");
1619+
}
16161620
var keys = new List<string>();
16171621
var keysCommon = new List<string> {
16181622
"RootModule",
@@ -1644,15 +1648,10 @@ public static IEnumerable<string> GetModuleManifestKeys(Version powershellVersio
16441648
"HelpInfoURI",
16451649
"DefaultCommandPrefix"};
16461650
keys.AddRange(keysCommon);
1647-
if (powershellVersion.Equals(new Version("5.0")))
1651+
if (powershellVersion.Major == 5)
16481652
{
16491653
keys.Add("DscResourcesToExport");
16501654
}
1651-
else if (!powershellVersion.Equals(new Version("4.0"))
1652-
&& !powershellVersion.Equals(new Version("3.0")))
1653-
{
1654-
throw new ArgumentException("Invalid PowerShell version. Choose from 3.0, 4.0 or 5.0");
1655-
}
16561655
return keys;
16571656
}
16581657

@@ -1666,15 +1665,50 @@ public static IEnumerable<string> GetDeprecatedModuleManifestKeys()
16661665
}
16671666

16681667
/// <summary>
1669-
/// Checks if a given file is a valid PowerShell module manifest
1668+
/// Get a mapping between string type keys and StatementAsts from module manifest hashtable ast
1669+
///
1670+
/// This is a workaround as SafeGetValue is not supported on PS v5 and below.
16701671
/// </summary>
1671-
/// <param name="filepath">Path to module manifest</param>
1672-
/// <returns>true if given filepath points to a module manifest, otherwise false</returns>
1673-
public static bool IsModuleManifest(string filepath)
1672+
/// <param name="hast">Hashtable Ast obtained from module manifest</param>
1673+
/// <returns>A dictionary that maps string keys to values of StatementAst type</returns>
1674+
private static Dictionary<string, StatementAst> GetMapFromHashtableAst(HashtableAst hast)
16741675
{
1675-
// 4.0 and 3.0 contain the same keys. Hence, compare only with 4.0.
1676-
return IsModuleManifest(filepath, new Version("5.0"))
1677-
|| IsModuleManifest(filepath, new Version("4.0"));
1676+
var map = new Dictionary<string, StatementAst>(StringComparer.OrdinalIgnoreCase);
1677+
foreach (var pair in hast.KeyValuePairs)
1678+
{
1679+
var key = pair.Item1 as StringConstantExpressionAst;
1680+
if (key == null)
1681+
{
1682+
return null;
1683+
}
1684+
map[key.Value] = pair.Item2;
1685+
}
1686+
return map;
1687+
}
1688+
1689+
/// <summary>
1690+
/// Checks if the version is supported
1691+
///
1692+
/// PowerShell versions with Major 5, 4 and 3 are supported
1693+
/// </summary>
1694+
/// <param name="version">PowerShell version</param>
1695+
/// <returns>true if the given version is supported else false</returns>
1696+
public static bool IsPowerShellVersionSupported(Version version)
1697+
{
1698+
if (version == null)
1699+
{
1700+
throw new ArgumentNullException("version");
1701+
}
1702+
1703+
switch(version.Major)
1704+
{
1705+
case 5:
1706+
case 4:
1707+
case 3:
1708+
return true;
1709+
default:
1710+
return false;
1711+
}
16781712
}
16791713

16801714
/// <summary>
@@ -1683,17 +1717,18 @@ public static bool IsModuleManifest(string filepath)
16831717
/// <param name="filepath">Path to module manifest</param>
16841718
/// <param name="powershellVersion">Version parameter with valid values: 5.0, 4.0 and 3.0</param>
16851719
/// <returns>true if given filepath points to a module manifest, otherwise false</returns>
1686-
public static bool IsModuleManifest(string filepath, Version powershellVersion)
1720+
public static bool IsModuleManifest(string filepath, Version powershellVersion = null)
16871721
{
16881722
Token[] tokens;
16891723
ParseError[] errors;
16901724
if (filepath == null)
16911725
{
16921726
throw new ArgumentNullException("filepath");
16931727
}
1694-
if (powershellVersion == null)
1728+
if (powershellVersion != null
1729+
&& !IsPowerShellVersionSupported(powershellVersion))
16951730
{
1696-
throw new ArgumentNullException("powershellVersion");
1731+
return false;
16971732
}
16981733
if (!Path.GetExtension(filepath).Equals(".psd1", StringComparison.OrdinalIgnoreCase))
16991734
{
@@ -1708,28 +1743,45 @@ public static bool IsModuleManifest(string filepath, Version powershellVersion)
17081743
{
17091744
return false;
17101745
}
1711-
var validKeys = GetModuleManifestKeys(powershellVersion);
1712-
var allKeys = validKeys.Concat(GetDeprecatedModuleManifestKeys());
1713-
1714-
// check if all the keys in hast.keyvaluepairs are present in keys
1715-
int matchCount = 0;
1716-
foreach(var pair in hast.KeyValuePairs)
1746+
var map = GetMapFromHashtableAst(hast);
1747+
var deprecatedKeys = GetDeprecatedModuleManifestKeys();
1748+
IEnumerable<string> allKeys;
1749+
if (powershellVersion != null)
17171750
{
1718-
var pairKey = pair.Item1 as StringConstantExpressionAst;
1719-
if (pairKey == null)
1720-
{
1721-
break;
1722-
}
1723-
foreach(var key in allKeys)
1751+
allKeys = GetModuleManifestKeys(powershellVersion);
1752+
}
1753+
else
1754+
{
1755+
Version version = null;
1756+
if (map.ContainsKey("PowerShellVersion"))
17241757
{
1725-
if (key.Equals(pairKey.Value, StringComparison.OrdinalIgnoreCase))
1758+
var versionStrAst = map["PowerShellVersion"].Find(x => x is StringConstantExpressionAst, false);
1759+
if (versionStrAst != null)
17261760
{
1727-
matchCount++;
1728-
break;
1761+
try
1762+
{
1763+
version = new Version((versionStrAst as StringConstantExpressionAst).Value);
1764+
}
1765+
catch
1766+
{
1767+
// we just ignore if the value is not a valid version
1768+
}
17291769
}
17301770
}
1771+
if (version != null
1772+
&& IsPowerShellVersionSupported(version))
1773+
{
1774+
allKeys = GetModuleManifestKeys(version);
1775+
}
1776+
else
1777+
{
1778+
// default to version 5.0
1779+
allKeys = GetModuleManifestKeys(new Version("5.0"));
1780+
}
17311781
}
1732-
return matchCount == hast.KeyValuePairs.Count;
1782+
1783+
// check if the keys given in module manifest are a proper subset of Keys
1784+
return map.Keys.All(x => allKeys.Concat(deprecatedKeys).Contains(x, StringComparer.OrdinalIgnoreCase));
17331785
}
17341786
#endregion Methods
17351787
}

0 commit comments

Comments
 (0)