Skip to content

Commit

Permalink
Fixes exception calling RuleSource value #1343 (#1344)
Browse files Browse the repository at this point in the history
  • Loading branch information
BernieWhite authored Nov 18, 2022
1 parent 06df37e commit ce44a88
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 33 deletions.
6 changes: 6 additions & 0 deletions docs/CHANGELOG-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers

## Unreleased

What's changed since v2.6.0:

- Bug fixes:
- Fixes exception calling `RuleSource` value cannot be null by @BernieWhite.
[#1343](https://github.com/microsoft/PSRule/issues/1343)

## v2.6.0

What's changed since v2.5.3:
Expand Down
9 changes: 0 additions & 9 deletions src/PSRule/Common/Engine.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.IO;
using PSRule.Configuration;

namespace PSRule
{
internal static partial class Engine
{
internal static string GetLocalPath()
{
return PSRuleOption.GetRootedBasePath(Path.GetDirectoryName(AppContext.BaseDirectory));
}

internal static string GetVersion()
{
return _Version;
Expand Down
6 changes: 6 additions & 0 deletions src/PSRule/Configuration/PSRuleOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,9 @@ public static string GetFilePath(string path)
/// <returns>A absolute path.</returns>
internal static string GetRootedPath(string path, bool normalize = false, string basePath = null)
{
if (string.IsNullOrEmpty(path))
path = string.Empty;

basePath ??= GetWorkingPath();
var rootedPath = Path.IsPathRooted(path) ? Path.GetFullPath(path) : Path.GetFullPath(Path.Combine(basePath, path));
return normalize ? rootedPath.Replace(Backslash, Slash) : rootedPath;
Expand All @@ -558,6 +561,9 @@ internal static string GetRootedPath(string path, bool normalize = false, string
/// </remarks>
internal static string GetRootedBasePath(string path, bool normalize = false)
{
if (string.IsNullOrEmpty(path))
path = string.Empty;

var rootedPath = GetRootedPath(path);
var basePath = rootedPath.Length > 0 && IsSeparator(rootedPath[rootedPath.Length - 1])
? rootedPath
Expand Down
15 changes: 4 additions & 11 deletions src/PSRule/Help/MarkdownStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@ public void SkipWhitespace()
/// If the current character and sequential characters are line ending control characters, skip ahead.
/// </summary>
/// <param name="max">The number of line endings to skip. When max is 0, sequential line endings will be skipped.</param>
/// <param name="ignoreEscaping">Determines if escaped characters are skipped.</param>
/// <returns>The number of line endings skipped.</returns>
public int SkipLineEnding(int max = 1, bool ignoreEscaping = false)
{
var skipped = 0;

while ((Current == CarrageReturn || Current == NewLine) && (max == 0 || skipped < max))
{
if (Remaining == 0)
Expand All @@ -171,7 +171,7 @@ public int SkipLineEnding(int max = 1, bool ignoreEscaping = false)
if (Current == CarrageReturn && Peak() == NewLine)
Next();

Next(ignoreEscaping: ignoreEscaping);
Next(ignoreEscaping);
skipped++;
}
return skipped;
Expand Down Expand Up @@ -205,47 +205,40 @@ public bool Skip(char c)
/// Skip ahead if the current character is expected. Keep skipping when the character is repeated.
/// </summary>
/// <param name="c">The character to skip.</param>
/// <param name="max">The maximum number of characters to skip.</param>
/// <returns>The number of characters that where skipped.</returns>
public int Skip(char c, int max)
{
var skipped = 0;

while (Current == c && (max == 0 || skipped < max))
{
Next();

skipped++;
}

return skipped;
}

public int Skip(string sequence, int max = 0, bool ignoreEscaping = false)
{
var skipped = 0;

while (IsSequence(sequence) && (max == 0 || skipped < max))
{
Skip(sequence.Length, ignoreEscaping);

skipped++;
}

return skipped;
}

/// <summary>
/// Skip ahead a number of characters. Use Next() in preference of Skip if the number to skip is 1.
/// </summary>
/// <param name="toSkip">The number of characters to skip</param>
/// <param name="ignoreEscaping">Determines if escaped characters are skipped.</param>
public void Skip(int toSkip, bool ignoreEscaping = false)
{
toSkip = HasRemaining(toSkip) ? toSkip : Remaining;

for (var i = 0; i < toSkip; i++)
{
Next(ignoreEscaping);
}
}

/// <summary>
Expand Down
15 changes: 13 additions & 2 deletions src/PSRule/Pipeline/CommandLineBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.IO;
using PSRule.Configuration;

namespace PSRule.Pipeline
Expand All @@ -22,7 +24,7 @@ public static class CommandLineBuilder
/// <returns>A builder object to configure the pipeline.</returns>
public static IInvokePipelineBuilder Invoke(string[] module, PSRuleOption option, IHostContext hostContext)
{
var sourcePipeline = new SourcePipelineBuilder(hostContext, option);
var sourcePipeline = new SourcePipelineBuilder(hostContext, option, GetLocalPath());
for (var i = 0; i < module.Length; i++)
sourcePipeline.ModuleByName(module[i]);

Expand All @@ -44,7 +46,7 @@ public static IInvokePipelineBuilder Invoke(string[] module, PSRuleOption option
/// <returns>A builder object to configure the pipeline.</returns>
public static IInvokePipelineBuilder Assert(string[] module, PSRuleOption option, IHostContext hostContext)
{
var sourcePipeline = new SourcePipelineBuilder(hostContext, option);
var sourcePipeline = new SourcePipelineBuilder(hostContext, option, GetLocalPath());
for (var i = 0; module != null && i < module.Length; i++)
sourcePipeline.ModuleByName(module[i]);

Expand All @@ -53,5 +55,14 @@ public static IInvokePipelineBuilder Assert(string[] module, PSRuleOption option
pipeline.Configure(option);
return pipeline;
}

internal static string GetLocalPath()
{
if (string.IsNullOrEmpty(AppContext.BaseDirectory) ||
string.IsNullOrEmpty(Path.GetDirectoryName(AppContext.BaseDirectory)))
return null;

return PSRuleOption.GetRootedBasePath(Path.GetDirectoryName(AppContext.BaseDirectory));
}
}
}
8 changes: 6 additions & 2 deletions src/PSRule/Pipeline/SourcePipeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,14 @@ public sealed class SourcePipelineBuilder : ISourcePipelineBuilder, ISourceComma
private readonly bool _UseDefaultPath;
private readonly string _LocalPath;

internal SourcePipelineBuilder(IHostContext hostContext, PSRuleOption option)
internal SourcePipelineBuilder(IHostContext hostContext, PSRuleOption option, string localPath = null)
{
_Source = new Dictionary<string, Source>(StringComparer.OrdinalIgnoreCase);
_HostContext = hostContext;
_Writer = new HostPipelineWriter(hostContext, option, ShouldProcess);
_Writer.EnterScope("[Discovery.Source]");
_UseDefaultPath = option == null || option.Include == null || option.Include.Path == null;
_LocalPath = Engine.GetLocalPath();
_LocalPath = localPath;

// Include paths from options
if (!_UseDefaultPath)
Expand Down Expand Up @@ -243,6 +243,10 @@ private string FindModule(string name)
/// </summary>
private bool TryPackagedModule(string name, out string path)
{
path = null;
if (_LocalPath == null)
return false;

Log($"Looking for modules in: {_LocalPath}");
path = PSRuleOption.GetRootedBasePath(Path.Combine(_LocalPath, "Modules", name));
return System.IO.Directory.Exists(path);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
Expand All @@ -13,7 +13,7 @@

namespace PSRule
{
public sealed class ConfigTests
public sealed class ModuleConfigTests
{
[Theory]
[InlineData("ModuleConfig.Rule.yaml")]
Expand All @@ -26,21 +26,25 @@ public void ReadModuleConfig(string path)
Assert.Equal("Configuration1", configuration[0].Name);
}

private PSRuleOption GetOption()
#region Helper methods

private static PSRuleOption GetOption()
{
return new PSRuleOption();
}

private Source[] GetSource(string path)
private static Source[] GetSource(string path)
{
var builder = new SourcePipelineBuilder(null, null);
builder.Directory(GetSourcePath(path));
return builder.Build();
}

private string GetSourcePath(string fileName)
private static string GetSourcePath(string fileName)
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
}

#endregion Helper methods
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@

namespace PSRule
{
[Trait(LANGUAGE, LANGUAGEELEMENT)]
public sealed class ConfigurationTests
public sealed class PSRuleOptionTests
{
private const string LANGUAGE = "Language";
private const string LANGUAGEELEMENT = "Variable";
[Fact]
public void GetRootedBasePath()
{
var pwd = Directory.GetCurrentDirectory();
var basePwd = $"{pwd}{Path.DirectorySeparatorChar}";
Assert.Equal(basePwd, PSRuleOption.GetRootedBasePath(null));
Assert.Equal(basePwd, PSRuleOption.GetRootedBasePath(pwd));
Assert.Equal(pwd, PSRuleOption.GetRootedPath(null));
Assert.Equal(pwd, PSRuleOption.GetRootedPath(pwd));
}

[Fact]
public void Configuration()
Expand Down Expand Up @@ -67,6 +74,8 @@ public void GetObjectArrayFromYaml()
Assert.Equal("East US", pso.PropertyValue<string>("location"));
}

#region Helper methods

private static Runtime.Configuration GetConfigurationHelper(PSRuleOption option)
{
var builder = new OptionContextBuilder(option, null, null, null);
Expand Down Expand Up @@ -97,5 +106,7 @@ private static string GetSourcePath(string fileName)
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
}

#endregion Helper methods
}
}

0 comments on commit ce44a88

Please sign in to comment.