зеркало из https://github.com/microsoft/PSRule.git
Code quality updates (#1784)
This commit is contained in:
Родитель
7203d44297
Коммит
bb67aab55b
|
@ -29,6 +29,8 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
|
|
@ -32,6 +32,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PSRule.Tool.Tests", "tests\
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PSRule.CommandLine", "src\PSRule.CommandLine\PSRule.CommandLine.csproj", "{9A556814-8E9D-4C76-8F6D-1AF2DA23A9E0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PSRule.CommandLine.Tests", "tests\PSRule.CommandLine.Tests\PSRule.CommandLine.Tests.csproj", "{C25E2FC1-E306-4D99-925C-15E5DD51F6A2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -82,6 +84,10 @@ Global
|
|||
{9A556814-8E9D-4C76-8F6D-1AF2DA23A9E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9A556814-8E9D-4C76-8F6D-1AF2DA23A9E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9A556814-8E9D-4C76-8F6D-1AF2DA23A9E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C25E2FC1-E306-4D99-925C-15E5DD51F6A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C25E2FC1-E306-4D99-925C-15E5DD51F6A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C25E2FC1-E306-4D99-925C-15E5DD51F6A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C25E2FC1-E306-4D99-925C-15E5DD51F6A2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -89,6 +95,7 @@ Global
|
|||
GlobalSection(NestedProjects) = preSolution
|
||||
{D3488CE2-779F-4474-B38A-F894A4B689F7} = {E0EA0CBA-96C5-4447-8B69-BC13EF0D7A4A}
|
||||
{DA46C891-08F1-4D01-9F98-1F8BB10CAFEC} = {E0EA0CBA-96C5-4447-8B69-BC13EF0D7A4A}
|
||||
{C25E2FC1-E306-4D99-925C-15E5DD51F6A2} = {E0EA0CBA-96C5-4447-8B69-BC13EF0D7A4A}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {533491EB-BAE9-472E-B57F-A675ECD335B5}
|
||||
|
|
|
@ -162,13 +162,13 @@ internal static class GitHelper
|
|||
return $"diff --diff-filter={filter} --ignore-submodules=all --name-only --no-renames {target}";
|
||||
}
|
||||
|
||||
private static bool TryReadHead(string path, out string value)
|
||||
internal static bool TryReadHead(string path, out string value)
|
||||
{
|
||||
value = null;
|
||||
return TryGitFile(path, GIT_HEAD, out var filePath) && TryCommit(filePath, out value, out _);
|
||||
}
|
||||
|
||||
private static bool TryReadCommit(string path, out string value)
|
||||
internal static bool TryReadCommit(string path, out string value)
|
||||
{
|
||||
value = null;
|
||||
if (!TryGitFile(path, GIT_HEAD, out var filePath))
|
||||
|
@ -182,8 +182,7 @@ internal static class GitHelper
|
|||
|
||||
private static bool TryGitFile(string path, string file, out string filePath)
|
||||
{
|
||||
path ??= Environment.GetRootedBasePath(GIT_DEFAULT_PATH);
|
||||
filePath = Path.Combine(path, file);
|
||||
filePath = Path.Combine(Environment.GetRootedBasePath(path ?? GIT_DEFAULT_PATH), file);
|
||||
return File.Exists(filePath);
|
||||
}
|
||||
|
||||
|
@ -191,6 +190,9 @@ internal static class GitHelper
|
|||
{
|
||||
value = null;
|
||||
isRef = false;
|
||||
if (!File.Exists(path))
|
||||
return false;
|
||||
|
||||
var lines = File.ReadAllLines(path);
|
||||
if (lines == null || lines.Length == 0)
|
||||
return false;
|
||||
|
|
|
@ -198,7 +198,7 @@ public sealed class PSRuleOption : IEquatable<PSRuleOption>, IBaselineV1Spec
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merge two option instances by repacing any unset properties from <paramref name="o1"/> with <paramref name="o2"/> values.
|
||||
/// Merge two option instances by replacing any unset properties from <paramref name="o1"/> with <paramref name="o2"/> values.
|
||||
/// Values from <paramref name="o1"/> that are set are not overridden.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="PSRuleOption"/> instance combining options from both instances.</returns>
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\DocumentStrings.es-us.resx">
|
||||
<EmbeddedResource Update="Resources\DocumentStrings.es-US.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\DocumentStrings.es.resx">
|
||||
|
|
|
@ -65,7 +65,7 @@ public static class CommandLineBuilder
|
|||
builder.ModuleByName(module[i], version);
|
||||
}
|
||||
|
||||
for (var i = 0; option.Include.Module != null && i < option.Include.Module.Length; i++)
|
||||
for (var i = 0; option?.Include?.Module != null && i < option.Include.Module.Length; i++)
|
||||
{
|
||||
var version = file != null && file.Modules.TryGetValue(option.Include.Module[i], out var entry) ? entry.Version.ToString() : null;
|
||||
builder.ModuleByName(option.Include.Module[i], version);
|
||||
|
|
|
@ -11,27 +11,6 @@ using PSRule.Rules;
|
|||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a pipeline for getting help from rules.
|
||||
/// </summary>
|
||||
public interface IHelpPipelineBuilder : IPipelineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the full help output for a rule.
|
||||
/// </summary>
|
||||
void Full();
|
||||
|
||||
/// <summary>
|
||||
/// Open or show online help for a rule if it exists.
|
||||
/// </summary>
|
||||
void Online();
|
||||
|
||||
/// <summary>
|
||||
/// Filter by name.
|
||||
/// </summary>
|
||||
void Name(string[] name);
|
||||
}
|
||||
|
||||
internal sealed class GetRuleHelpPipelineBuilder : PipelineBuilderBase, IHelpPipelineBuilder
|
||||
{
|
||||
private bool _Full;
|
||||
|
|
|
@ -5,17 +5,6 @@ using PSRule.Configuration;
|
|||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a get pipeline.
|
||||
/// </summary>
|
||||
public interface IGetPipelineBuilder : IPipelineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if the returned rules also include rule dependencies.
|
||||
/// </summary>
|
||||
void IncludeDependencies();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A helper to construct a get pipeline.
|
||||
/// </summary>
|
||||
|
|
|
@ -2,133 +2,9 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
using System.Management.Automation;
|
||||
using PSRule.Configuration;
|
||||
using PSRule.Options;
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a pipeline to return target objects.
|
||||
/// </summary>
|
||||
public interface IGetTargetPipelineBuilder : IPipelineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies a path for reading input objects from disk.
|
||||
/// </summary>
|
||||
void InputPath(string[] path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A helper to construct the pipeline for Assert-PSRule.
|
||||
/// </summary>
|
||||
internal sealed class GetTargetPipelineBuilder : PipelineBuilderBase, IGetTargetPipelineBuilder
|
||||
{
|
||||
private InputPathBuilder _InputPath;
|
||||
|
||||
internal GetTargetPipelineBuilder(Source[] source, IHostContext hostContext)
|
||||
: base(source, hostContext)
|
||||
{
|
||||
_InputPath = null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IPipelineBuilder Configure(PSRuleOption option)
|
||||
{
|
||||
if (option == null)
|
||||
return this;
|
||||
|
||||
base.Configure(option);
|
||||
|
||||
Option.Output = new OutputOption();
|
||||
Option.Output.Culture = GetCulture(option.Output.Culture);
|
||||
|
||||
ConfigureBinding(option);
|
||||
Option.Requires = new RequiresOption(option.Requires);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void InputPath(string[] path)
|
||||
{
|
||||
if (path == null || path.Length == 0)
|
||||
return;
|
||||
|
||||
PathFilter required = null;
|
||||
if (TryChangedFiles(out var files))
|
||||
{
|
||||
required = PathFilter.Create(Environment.GetWorkingPath(), path);
|
||||
path = files;
|
||||
}
|
||||
|
||||
var builder = new InputPathBuilder(GetOutput(), Environment.GetWorkingPath(), "*", GetInputFilter(), required);
|
||||
builder.Add(path);
|
||||
_InputPath = builder;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IPipeline Build(IPipelineWriter writer = null)
|
||||
{
|
||||
return new GetTargetPipeline(PrepareContext(null, null, null), PrepareReader(), writer ?? PrepareWriter());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override PipelineInputStream PrepareReader()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Option.Input.ObjectPath))
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ReadObjectPath(sourceObject, next, Option.Input.ObjectPath, true);
|
||||
});
|
||||
}
|
||||
|
||||
if (Option.Input.Format == InputFormat.Yaml)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromYaml(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.Json)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromJson(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.Markdown)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromMarkdown(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.PowerShellData)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromPowerShellData(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.File)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromGitHead(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.Detect && _InputPath != null)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.DetectInputFormat(sourceObject, next);
|
||||
});
|
||||
}
|
||||
return new PipelineInputStream(VisitTargetObject, _InputPath, GetInputObjectSourceFilter());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A pipeline that gets target objects through the pipeline.
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using PSRule.Configuration;
|
||||
using PSRule.Options;
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to construct the pipeline for Assert-PSRule.
|
||||
/// </summary>
|
||||
internal sealed class GetTargetPipelineBuilder : PipelineBuilderBase, IGetTargetPipelineBuilder
|
||||
{
|
||||
private InputPathBuilder _InputPath;
|
||||
|
||||
internal GetTargetPipelineBuilder(Source[] source, IHostContext hostContext)
|
||||
: base(source, hostContext)
|
||||
{
|
||||
_InputPath = null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IPipelineBuilder Configure(PSRuleOption option)
|
||||
{
|
||||
if (option == null)
|
||||
return this;
|
||||
|
||||
base.Configure(option);
|
||||
|
||||
Option.Output = new OutputOption();
|
||||
Option.Output.Culture = GetCulture(option.Output.Culture);
|
||||
|
||||
ConfigureBinding(option);
|
||||
Option.Requires = new RequiresOption(option.Requires);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void InputPath(string[] path)
|
||||
{
|
||||
if (path == null || path.Length == 0)
|
||||
return;
|
||||
|
||||
PathFilter required = null;
|
||||
if (TryChangedFiles(out var files))
|
||||
{
|
||||
required = PathFilter.Create(Environment.GetWorkingPath(), path);
|
||||
path = files;
|
||||
}
|
||||
|
||||
var builder = new InputPathBuilder(GetOutput(), Environment.GetWorkingPath(), "*", GetInputFilter(), required);
|
||||
builder.Add(path);
|
||||
_InputPath = builder;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IPipeline Build(IPipelineWriter writer = null)
|
||||
{
|
||||
return new GetTargetPipeline(PrepareContext(null, null, null), PrepareReader(), writer ?? PrepareWriter());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override PipelineInputStream PrepareReader()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Option.Input.ObjectPath))
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ReadObjectPath(sourceObject, next, Option.Input.ObjectPath, true);
|
||||
});
|
||||
}
|
||||
|
||||
if (Option.Input.Format == InputFormat.Yaml)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromYaml(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.Json)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromJson(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.Markdown)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromMarkdown(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.PowerShellData)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromPowerShellData(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.File)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.ConvertFromGitHead(sourceObject, next);
|
||||
});
|
||||
}
|
||||
else if (Option.Input.Format == InputFormat.Detect && _InputPath != null)
|
||||
{
|
||||
AddVisitTargetObjectAction((sourceObject, next) =>
|
||||
{
|
||||
return PipelineReceiverActions.DetectInputFormat(sourceObject, next);
|
||||
});
|
||||
}
|
||||
return new PipelineInputStream(VisitTargetObject, _InputPath, GetInputObjectSourceFilter());
|
||||
}
|
||||
}
|
|
@ -6,117 +6,6 @@ using PSRule.Definitions;
|
|||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A host context for handling input and output emitted from the pipeline.
|
||||
/// </summary>
|
||||
public interface IHostContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if the pipeline is executing in a remote PowerShell session.
|
||||
/// </summary>
|
||||
bool InSession { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the pipeline encountered any errors.
|
||||
/// </summary>
|
||||
bool HadErrors { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a PowerShell preference variable.
|
||||
/// </summary>
|
||||
ActionPreference GetPreferenceVariable(string variableName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a named variable.
|
||||
/// </summary>
|
||||
T GetVariable<T>(string variableName);
|
||||
|
||||
/// <summary>
|
||||
/// Set the value of a named variable.
|
||||
/// </summary>
|
||||
void SetVariable<T>(string variableName, T value);
|
||||
|
||||
/// <summary>
|
||||
/// Handle an error reported by the pipeline.
|
||||
/// </summary>
|
||||
void Error(ErrorRecord errorRecord);
|
||||
|
||||
/// <summary>
|
||||
/// Handle a warning reported by the pipeline.
|
||||
/// </summary>
|
||||
void Warning(string text);
|
||||
|
||||
/// <summary>
|
||||
/// Handle an informational record reported by the pipeline.
|
||||
/// </summary>
|
||||
void Information(InformationRecord informationRecord);
|
||||
|
||||
/// <summary>
|
||||
/// Handle a verbose message reported by the pipeline.
|
||||
/// </summary>
|
||||
void Verbose(string text);
|
||||
|
||||
/// <summary>
|
||||
/// Handle a debug message reported by the pipeline.
|
||||
/// </summary>
|
||||
void Debug(string text);
|
||||
|
||||
/// <summary>
|
||||
/// Handle an object emitted from the pipeline.
|
||||
/// </summary>
|
||||
void Object(object sendToPipeline, bool enumerateCollection);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a destructive action such as overwriting a file should be processed.
|
||||
/// </summary>
|
||||
bool ShouldProcess(string target, string action);
|
||||
|
||||
/// <summary>
|
||||
/// Get the current working path.
|
||||
/// </summary>
|
||||
string GetWorkingPath();
|
||||
}
|
||||
|
||||
internal static class HostContextExtensions
|
||||
{
|
||||
private const string ErrorPreference = "ErrorActionPreference";
|
||||
private const string WarningPreference = "WarningPreference";
|
||||
private const string InformationPreference = "InformationPreference";
|
||||
private const string VerbosePreference = "VerbosePreference";
|
||||
private const string DebugPreference = "DebugPreference";
|
||||
private const string AutoLoadingPreference = "PSModuleAutoLoadingPreference";
|
||||
|
||||
public static ActionPreference GetErrorPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(ErrorPreference);
|
||||
}
|
||||
|
||||
public static ActionPreference GetWarningPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(WarningPreference);
|
||||
}
|
||||
|
||||
public static ActionPreference GetInformationPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(InformationPreference);
|
||||
}
|
||||
|
||||
public static ActionPreference GetVerbosePreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(VerbosePreference);
|
||||
}
|
||||
|
||||
public static ActionPreference GetDebugPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(DebugPreference);
|
||||
}
|
||||
|
||||
public static PSModuleAutoLoadingPreference GetAutoLoadingPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetVariable<PSModuleAutoLoadingPreference>(AutoLoadingPreference);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A base class for custom host context instances.
|
||||
/// </summary>
|
||||
|
@ -206,98 +95,3 @@ public abstract class HostContext : IHostContext
|
|||
return Directory.GetCurrentDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The host context used for PowerShell-based pipelines.
|
||||
/// </summary>
|
||||
public sealed class PSHostContext : IHostContext
|
||||
{
|
||||
internal readonly PSCmdlet CmdletContext;
|
||||
internal readonly EngineIntrinsics ExecutionContext;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool InSession { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool HadErrors { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of a PowerShell-based host context.
|
||||
/// </summary>
|
||||
public PSHostContext(PSCmdlet commandRuntime, EngineIntrinsics executionContext)
|
||||
{
|
||||
InSession = false;
|
||||
CmdletContext = commandRuntime;
|
||||
ExecutionContext = executionContext;
|
||||
InSession = executionContext != null && executionContext.SessionState.PSVariable.GetValue("PSSenderInfo") != null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ActionPreference GetPreferenceVariable(string variableName)
|
||||
{
|
||||
return ExecutionContext == null
|
||||
? ActionPreference.SilentlyContinue
|
||||
: (ActionPreference)ExecutionContext.SessionState.PSVariable.GetValue(variableName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public T GetVariable<T>(string variableName)
|
||||
{
|
||||
return ExecutionContext == null ? default : (T)ExecutionContext.SessionState.PSVariable.GetValue(variableName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetVariable<T>(string variableName, T value)
|
||||
{
|
||||
CmdletContext.SessionState.PSVariable.Set(variableName, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldProcess(string target, string action)
|
||||
{
|
||||
return CmdletContext == null || CmdletContext.ShouldProcess(target, action);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(ErrorRecord errorRecord)
|
||||
{
|
||||
CmdletContext.WriteError(errorRecord);
|
||||
HadErrors = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warning(string text)
|
||||
{
|
||||
CmdletContext.WriteWarning(text);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Information(InformationRecord informationRecord)
|
||||
{
|
||||
CmdletContext.WriteInformation(informationRecord);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Verbose(string text)
|
||||
{
|
||||
CmdletContext.WriteVerbose(text);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Debug(string text)
|
||||
{
|
||||
CmdletContext.WriteDebug(text);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Object(object sendToPipeline, bool enumerateCollection)
|
||||
{
|
||||
CmdletContext.WriteObject(sendToPipeline, enumerateCollection);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string GetWorkingPath()
|
||||
{
|
||||
return ExecutionContext.SessionState.Path.CurrentFileSystemLocation.Path;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Management.Automation;
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
internal static class HostContextExtensions
|
||||
{
|
||||
private const string ErrorPreference = "ErrorActionPreference";
|
||||
private const string WarningPreference = "WarningPreference";
|
||||
private const string InformationPreference = "InformationPreference";
|
||||
private const string VerbosePreference = "VerbosePreference";
|
||||
private const string DebugPreference = "DebugPreference";
|
||||
private const string AutoLoadingPreference = "PSModuleAutoLoadingPreference";
|
||||
|
||||
public static ActionPreference GetErrorPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(ErrorPreference);
|
||||
}
|
||||
|
||||
public static ActionPreference GetWarningPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(WarningPreference);
|
||||
}
|
||||
|
||||
public static ActionPreference GetInformationPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(InformationPreference);
|
||||
}
|
||||
|
||||
public static ActionPreference GetVerbosePreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(VerbosePreference);
|
||||
}
|
||||
|
||||
public static ActionPreference GetDebugPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetPreferenceVariable(DebugPreference);
|
||||
}
|
||||
|
||||
public static PSModuleAutoLoadingPreference GetAutoLoadingPreference(this IHostContext hostContext)
|
||||
{
|
||||
return hostContext.GetVariable<PSModuleAutoLoadingPreference>(AutoLoadingPreference);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a get pipeline.
|
||||
/// </summary>
|
||||
public interface IGetPipelineBuilder : IPipelineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if the returned rules also include rule dependencies.
|
||||
/// </summary>
|
||||
void IncludeDependencies();
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a pipeline to return target objects.
|
||||
/// </summary>
|
||||
public interface IGetTargetPipelineBuilder : IPipelineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies a path for reading input objects from disk.
|
||||
/// </summary>
|
||||
void InputPath(string[] path);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a pipeline for getting help from rules.
|
||||
/// </summary>
|
||||
public interface IHelpPipelineBuilder : IPipelineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the full help output for a rule.
|
||||
/// </summary>
|
||||
void Full();
|
||||
|
||||
/// <summary>
|
||||
/// Open or show online help for a rule if it exists.
|
||||
/// </summary>
|
||||
void Online();
|
||||
|
||||
/// <summary>
|
||||
/// Filter by name.
|
||||
/// </summary>
|
||||
void Name(string[] name);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Management.Automation;
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A host context for handling input and output emitted from the pipeline.
|
||||
/// </summary>
|
||||
public interface IHostContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if the pipeline is executing in a remote PowerShell session.
|
||||
/// </summary>
|
||||
bool InSession { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the pipeline encountered any errors.
|
||||
/// </summary>
|
||||
bool HadErrors { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a PowerShell preference variables.
|
||||
/// These variables are commonly used to control logging output.
|
||||
/// Preference variables include: <c>ErrorActionPreference</c>, <c>WarningPreference</c>, <c>InformationPreference</c>, <c>VerbosePreference</c>, <c>DebugPreference</c>
|
||||
/// </summary>
|
||||
ActionPreference GetPreferenceVariable(string variableName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a named variable.
|
||||
/// </summary>
|
||||
T GetVariable<T>(string variableName);
|
||||
|
||||
/// <summary>
|
||||
/// Set the value of a named variable.
|
||||
/// </summary>
|
||||
void SetVariable<T>(string variableName, T value);
|
||||
|
||||
/// <summary>
|
||||
/// Handle an error reported by the pipeline.
|
||||
/// </summary>
|
||||
void Error(ErrorRecord errorRecord);
|
||||
|
||||
/// <summary>
|
||||
/// Handle a warning reported by the pipeline.
|
||||
/// </summary>
|
||||
void Warning(string text);
|
||||
|
||||
/// <summary>
|
||||
/// Handle an informational record reported by the pipeline.
|
||||
/// </summary>
|
||||
void Information(InformationRecord informationRecord);
|
||||
|
||||
/// <summary>
|
||||
/// Handle a verbose message reported by the pipeline.
|
||||
/// </summary>
|
||||
void Verbose(string text);
|
||||
|
||||
/// <summary>
|
||||
/// Handle a debug message reported by the pipeline.
|
||||
/// </summary>
|
||||
void Debug(string text);
|
||||
|
||||
/// <summary>
|
||||
/// Handle an object emitted from the pipeline.
|
||||
/// </summary>
|
||||
void Object(object sendToPipeline, bool enumerateCollection);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a destructive action such as overwriting a file should be processed.
|
||||
/// </summary>
|
||||
bool ShouldProcess(string target, string action);
|
||||
|
||||
/// <summary>
|
||||
/// Get the current working path.
|
||||
/// </summary>
|
||||
string GetWorkingPath();
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a list of sources for a command-line tool pipeline.
|
||||
/// </summary>
|
||||
public interface ISourceCommandLineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Add loose files as a source.
|
||||
/// </summary>
|
||||
/// <param name="path">An array of file or directory paths containing one or more rule files.</param>
|
||||
/// <param name="excludeDefaultRulePath">Determine if the default rule path is excluded. When set to <c>true</c> the default rule path is excluded.</param>
|
||||
void Directory(string[] path, bool excludeDefaultRulePath = false);
|
||||
|
||||
/// <summary>
|
||||
/// Add loose files as a source.
|
||||
/// </summary>
|
||||
/// <param name="path">A file or directory path containing one or more rule files.</param>
|
||||
/// <param name="excludeDefaultRulePath">Determine if the default rule path is excluded. When set to <c>true</c> the default rule path is excluded.</param>
|
||||
void Directory(string path, bool excludeDefaultRulePath = false);
|
||||
|
||||
/// <summary>
|
||||
/// Add a module source.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the module.</param>
|
||||
/// <param name="version">A specific version of the module.</param>
|
||||
void ModuleByName(string name, string version = null);
|
||||
|
||||
/// <summary>
|
||||
/// Build a list of sources for executing within PSRule.
|
||||
/// </summary>
|
||||
/// <returns>A list of sources.</returns>
|
||||
Source[] Build();
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Management.Automation;
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a list of sources for a PowerShell pipeline.
|
||||
/// </summary>
|
||||
public interface ISourcePipelineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if PowerShell should automatically load the module.
|
||||
/// </summary>
|
||||
bool ShouldLoadModule { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Log a verbose message for scanning sources.
|
||||
/// </summary>
|
||||
void VerboseScanSource(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Log a verbose message for source modules.
|
||||
/// </summary>
|
||||
void VerboseFoundModules(int count);
|
||||
|
||||
/// <summary>
|
||||
/// Log a verbose message for scanning for modules.
|
||||
/// </summary>
|
||||
void VerboseScanModule(string moduleName);
|
||||
|
||||
/// <summary>
|
||||
/// Add loose files as a source.
|
||||
/// </summary>
|
||||
/// <param name="path">An array of file or directory paths containing one or more rule files.</param>
|
||||
/// <param name="excludeDefaultRulePath">Determine if the default rule path is excluded. When set to <c>true</c> the default rule path is excluded.</param>
|
||||
void Directory(string[] path, bool excludeDefaultRulePath = false);
|
||||
|
||||
/// <summary>
|
||||
/// Add loose files as a source.
|
||||
/// </summary>
|
||||
/// <param name="path">A file or directory path containing one or more rule files.</param>
|
||||
/// <param name="excludeDefaultRulePath">Determine if the default rule path is excluded. When set to <c>true</c> the default rule path is excluded.</param>
|
||||
void Directory(string path, bool excludeDefaultRulePath = false);
|
||||
|
||||
/// <summary>
|
||||
/// Add a module source.
|
||||
/// </summary>
|
||||
/// <param name="module">The module info.</param>
|
||||
void Module(PSModuleInfo[] module);
|
||||
|
||||
/// <summary>
|
||||
/// Build a list of sources for executing within PSRule.
|
||||
/// </summary>
|
||||
/// <returns>A list of sources.</returns>
|
||||
Source[] Build();
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Management.Automation;
|
||||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// The host context used for PowerShell-based pipelines.
|
||||
/// </summary>
|
||||
public sealed class PSHostContext : IHostContext
|
||||
{
|
||||
internal readonly PSCmdlet CmdletContext;
|
||||
internal readonly EngineIntrinsics ExecutionContext;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool InSession { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool HadErrors { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of a PowerShell-based host context.
|
||||
/// </summary>
|
||||
public PSHostContext(PSCmdlet commandRuntime, EngineIntrinsics executionContext)
|
||||
{
|
||||
InSession = false;
|
||||
CmdletContext = commandRuntime;
|
||||
ExecutionContext = executionContext;
|
||||
InSession = executionContext != null && executionContext.SessionState.PSVariable.GetValue("PSSenderInfo") != null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ActionPreference GetPreferenceVariable(string variableName)
|
||||
{
|
||||
return ExecutionContext == null
|
||||
? ActionPreference.SilentlyContinue
|
||||
: (ActionPreference)ExecutionContext.SessionState.PSVariable.GetValue(variableName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public T GetVariable<T>(string variableName)
|
||||
{
|
||||
return ExecutionContext == null ? default : (T)ExecutionContext.SessionState.PSVariable.GetValue(variableName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetVariable<T>(string variableName, T value)
|
||||
{
|
||||
CmdletContext.SessionState.PSVariable.Set(variableName, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldProcess(string target, string action)
|
||||
{
|
||||
return CmdletContext == null || CmdletContext.ShouldProcess(target, action);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Error(ErrorRecord errorRecord)
|
||||
{
|
||||
CmdletContext.WriteError(errorRecord);
|
||||
HadErrors = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Warning(string text)
|
||||
{
|
||||
CmdletContext.WriteWarning(text);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Information(InformationRecord informationRecord)
|
||||
{
|
||||
CmdletContext.WriteInformation(informationRecord);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Verbose(string text)
|
||||
{
|
||||
CmdletContext.WriteVerbose(text);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Debug(string text)
|
||||
{
|
||||
CmdletContext.WriteDebug(text);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Object(object sendToPipeline, bool enumerateCollection)
|
||||
{
|
||||
CmdletContext.WriteObject(sendToPipeline, enumerateCollection);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string GetWorkingPath()
|
||||
{
|
||||
return ExecutionContext.SessionState.Path.CurrentFileSystemLocation.Path;
|
||||
}
|
||||
}
|
|
@ -11,95 +11,10 @@ using PSRule.Resources;
|
|||
|
||||
namespace PSRule.Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a list of sources for a PowerShell pipeline.
|
||||
/// </summary>
|
||||
public interface ISourcePipelineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if PowerShell should automatically load the module.
|
||||
/// </summary>
|
||||
bool ShouldLoadModule { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Log a verbose message for scanning sources.
|
||||
/// </summary>
|
||||
void VerboseScanSource(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Log a verbose message for source modules.
|
||||
/// </summary>
|
||||
void VerboseFoundModules(int count);
|
||||
|
||||
/// <summary>
|
||||
/// Log a verbose message for scanning for modules.
|
||||
/// </summary>
|
||||
void VerboseScanModule(string moduleName);
|
||||
|
||||
/// <summary>
|
||||
/// Add loose files as a source.
|
||||
/// </summary>
|
||||
/// <param name="path">An array of file or directory paths containing one or more rule files.</param>
|
||||
/// <param name="excludeDefaultRulePath">Determine if the default rule path is excluded. When set to <c>true</c> the default rule path is excluded.</param>
|
||||
void Directory(string[] path, bool excludeDefaultRulePath = false);
|
||||
|
||||
/// <summary>
|
||||
/// Add loose files as a source.
|
||||
/// </summary>
|
||||
/// <param name="path">A file or directory path containing one or more rule files.</param>
|
||||
/// <param name="excludeDefaultRulePath">Determine if the default rule path is excluded. When set to <c>true</c> the default rule path is excluded.</param>
|
||||
void Directory(string path, bool excludeDefaultRulePath = false);
|
||||
|
||||
/// <summary>
|
||||
/// Add a module source.
|
||||
/// </summary>
|
||||
/// <param name="module">The module info.</param>
|
||||
void Module(PSModuleInfo[] module);
|
||||
|
||||
/// <summary>
|
||||
/// Build a list of sources for executing within PSRule.
|
||||
/// </summary>
|
||||
/// <returns>A list of sources.</returns>
|
||||
Source[] Build();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a list of sources for a command-line tool pipeline.
|
||||
/// </summary>
|
||||
public interface ISourceCommandlineBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Add loose files as a source.
|
||||
/// </summary>
|
||||
/// <param name="path">An array of file or directory paths containing one or more rule files.</param>
|
||||
/// <param name="excludeDefaultRulePath">Determine if the default rule path is excluded. When set to <c>true</c> the default rule path is excluded.</param>
|
||||
void Directory(string[] path, bool excludeDefaultRulePath = false);
|
||||
|
||||
/// <summary>
|
||||
/// Add loose files as a source.
|
||||
/// </summary>
|
||||
/// <param name="path">A file or directory path containing one or more rule files.</param>
|
||||
/// <param name="excludeDefaultRulePath">Determine if the default rule path is excluded. When set to <c>true</c> the default rule path is excluded.</param>
|
||||
void Directory(string path, bool excludeDefaultRulePath = false);
|
||||
|
||||
/// <summary>
|
||||
/// Add a module source.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the module.</param>
|
||||
/// <param name="version">A specific version of the module.</param>
|
||||
void ModuleByName(string name, string version = null);
|
||||
|
||||
/// <summary>
|
||||
/// Build a list of sources for executing within PSRule.
|
||||
/// </summary>
|
||||
/// <returns>A list of sources.</returns>
|
||||
Source[] Build();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A helper to build a list of rule sources for discovery.
|
||||
/// </summary>
|
||||
public sealed class SourcePipelineBuilder : ISourcePipelineBuilder, ISourceCommandlineBuilder
|
||||
public sealed class SourcePipelineBuilder : ISourcePipelineBuilder, ISourceCommandLineBuilder
|
||||
{
|
||||
private const string SOURCE_FILE_EXTENSION_YAML = ".yaml";
|
||||
private const string SOURCE_FILE_EXTENSION_YML = ".yml";
|
||||
|
@ -213,8 +128,8 @@ public sealed class SourcePipelineBuilder : ISourcePipelineBuilder, ISourceComma
|
|||
/// <inheritdoc/>
|
||||
public void ModuleByName(string name, string version = null)
|
||||
{
|
||||
var basePath = FindModule(name, version) ?? throw new PipelineBuilderException(PSRuleResources.ModuleNotFound);
|
||||
var info = LoadManifest(basePath, name) ?? throw new PipelineBuilderException(PSRuleResources.ModuleNotFound);
|
||||
var basePath = FindModule(name, version) ?? throw ModuleNotFound(name, version);
|
||||
var info = LoadManifest(basePath, name) ?? throw ModuleNotFound(name, version);
|
||||
|
||||
VerboseScanModule(info.Name);
|
||||
var files = GetFiles(
|
||||
|
@ -356,7 +271,7 @@ public sealed class SourcePipelineBuilder : ISourcePipelineBuilder, ISourceComma
|
|||
if (value == null) return false;
|
||||
|
||||
if (value is string s)
|
||||
requiredAssemblies = new string[] { s };
|
||||
requiredAssemblies = [s];
|
||||
|
||||
if (value is Array array)
|
||||
requiredAssemblies = array.OfType<string>().ToArray();
|
||||
|
@ -397,9 +312,10 @@ public sealed class SourcePipelineBuilder : ISourcePipelineBuilder, ISourceComma
|
|||
return false;
|
||||
|
||||
foreach (var tag in module.Tags)
|
||||
{
|
||||
if (StringComparer.OrdinalIgnoreCase.Equals(RULE_MODULE_TAG, tag))
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -463,7 +379,7 @@ public sealed class SourcePipelineBuilder : ISourcePipelineBuilder, ISourceComma
|
|||
return null;
|
||||
|
||||
helpPath ??= Path.GetDirectoryName(path);
|
||||
return new SourceFile[] { new(path, null, sourceType, helpPath) };
|
||||
return [new(path, null, sourceType, helpPath)];
|
||||
}
|
||||
|
||||
private static SourceFile[] IncludePath(string path, string helpPath, string moduleName, bool excludeDefaultRulePath, RestrictScriptSource restrictScriptSource, string workspacePath)
|
||||
|
@ -558,4 +474,9 @@ public sealed class SourcePipelineBuilder : ISourcePipelineBuilder, ISourceComma
|
|||
{
|
||||
return _HostContext == null || _HostContext.ShouldProcess(target, action);
|
||||
}
|
||||
|
||||
private static PipelineBuilderException ModuleNotFound(string name, string version)
|
||||
{
|
||||
return new PipelineBuilderException(string.Format(Thread.CurrentThread.CurrentCulture, PSRuleResources.ModuleNotFound, name, version));
|
||||
}
|
||||
}
|
|
@ -430,7 +430,7 @@ namespace PSRule.Resources {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No valid module can be found with that name..
|
||||
/// Looks up a localized string similar to No valid module can be found with: Name={0}, Version={1}.
|
||||
/// </summary>
|
||||
internal static string ModuleNotFound {
|
||||
get {
|
||||
|
|
|
@ -368,7 +368,7 @@
|
|||
<value>Output written to the following file: '{0}'</value>
|
||||
</data>
|
||||
<data name="ModuleNotFound" xml:space="preserve">
|
||||
<value>No valid module can be found with that name.</value>
|
||||
<value>No valid module can be found with: Name={0}, Version={1}</value>
|
||||
</data>
|
||||
<data name="RuleMatchTrace" xml:space="preserve">
|
||||
<value>[PSRule][R][Trace] -- {0}</value>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
global using Xunit;
|
|
@ -0,0 +1,24 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>PSRule.CommandLine</RootNamespace>
|
||||
<ProjectGuid>{46127fdf-9241-4b8a-9868-012b89e3318e}</ProjectGuid>
|
||||
<LangVersion>12.0</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="xunit" Version="2.6.6" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace PSRule;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for <see cref="GitHelper"/>.
|
||||
/// </summary>
|
||||
public sealed class GitHelperTests
|
||||
{
|
||||
[Fact]
|
||||
public void TryReadHead_WhenValidPath_ShouldReturnGitHead()
|
||||
{
|
||||
var expectedHead = GetGitOutput();
|
||||
|
||||
Assert.True(GitHelper.TryReadHead("../../../../../.git/", out var actualHead));
|
||||
Assert.Equal(expectedHead, NormalizeBranch(actualHead));
|
||||
}
|
||||
|
||||
#region Helper methods
|
||||
|
||||
private static string NormalizeBranch(string actualHead)
|
||||
{
|
||||
return actualHead.Replace("refs/heads/", "");
|
||||
}
|
||||
|
||||
private static string GetGitOutput()
|
||||
{
|
||||
return File.ReadAllText("../../../../../.git/HEAD").Replace("ref: ", string.Empty).Replace("refs/heads/", string.Empty).Trim();
|
||||
}
|
||||
|
||||
#endregion Helper methods
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ProjectGuid>{DA46C891-08F1-4D01-9F98-1F8BB10CAFEC}</ProjectGuid>
|
||||
<ProjectGuid>{c1d2bc26-305a-4985-8dc5-177449ff2cfd}</ProjectGuid>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<IsPackable>false</IsPackable>
|
||||
<RootNamespace>PSRule.Tool</RootNamespace>
|
||||
|
|
Загрузка…
Ссылка в новой задаче