Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,26 @@ jobs:
fail-fast: false
matrix:
info:
- name: PS_5.1_x64_Windows
psversion: '5.1'
os: windows-latest
- name: PS_7.2_x64_Windows
psversion: '7.2.8'
psversion: '7.2.0'
os: windows-latest
- name: PS_7.2_x64_Linux
psversion: '7.2.8'
psversion: '7.2.0'
os: ubuntu-latest
- name: PS_7.3_x64_Windows
psversion: '7.3.1'
psversion: '7.3.0'
os: windows-latest
- name: PS_7.3_x64_Linux
psversion: '7.3.1'
psversion: '7.3.0'
os: ubuntu-latest
- name: PS_7.4_x64_Windows
psversion: '7.4.0'
os: windows-latest
- name: PS_7.4_x64_Linux
psversion: '7.4.0'
os: ubuntu-latest

steps:
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

+ Updated [YamlDotNet](https://github.com/aaubry/YamlDotNet) dependency to `13.7.1`
+ Provide workaround when importing the module more than once
+ Add support for Windows PowerShell 5.1
+ There are no guarantees that YamlDotNet will be loadable in case of conflicts, use PowerShell 7 so an ALC can be used

## v0.2.1 - 2023-10-13

Expand Down
37 changes: 37 additions & 0 deletions PowerShell-Yayaml.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{32EF6859-C1AA-4118-AFC3-811DE164F574}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yayaml", "src\Yayaml\Yayaml.csproj", "{598D032C-2373-4292-94DD-DFE934C57A3A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yayaml.Module", "src\Yayaml.Module\Yayaml.Module.csproj", "{4E17AD64-871F-4344-A60F-35408CD96C8E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{598D032C-2373-4292-94DD-DFE934C57A3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{598D032C-2373-4292-94DD-DFE934C57A3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{598D032C-2373-4292-94DD-DFE934C57A3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{598D032C-2373-4292-94DD-DFE934C57A3A}.Release|Any CPU.Build.0 = Release|Any CPU
{4E17AD64-871F-4344-A60F-35408CD96C8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E17AD64-871F-4344-A60F-35408CD96C8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E17AD64-871F-4344-A60F-35408CD96C8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E17AD64-871F-4344-A60F-35408CD96C8E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{598D032C-2373-4292-94DD-DFE934C57A3A} = {32EF6859-C1AA-4118-AFC3-811DE164F574}
{4E17AD64-871F-4344-A60F-35408CD96C8E} = {32EF6859-C1AA-4118-AFC3-811DE164F574}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F31C0D6D-8FFD-44FD-9607-D8BD49E9747D}
EndGlobalSection
EndGlobal
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ While there are a few other YAML modules out on the gallery this module includes
+ YAML 1.2 JSON parser and emitter
+ Support for custom schemas
+ Finer control over scalar, map, and sequence styles
+ Loads `YamlDotNet` in an Assembly Load Context to avoid DLL hell and cross assembly conflicts
+ Loads `YamlDotNet` in an Assembly Load Context to avoid DLL hell and cross assembly conflicts (PowerShell 7+ only)

There are schemas that support YAML 1.2 (default), 1.2 JSON, 1.1, and failsafe values.

Expand All @@ -22,7 +22,7 @@ See [Yayaml index](docs/en-US/Yayaml.md) for more details.

These cmdlets have the following requirements

* PowerShell v7.2 or newer
* PowerShell v5.1 or newer

## Examples

Expand Down
9 changes: 7 additions & 2 deletions Yayaml.build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ $UseNativeArguments = $PSVersionTable.PSVersion.Major -gt 7 -or ($PSVersionTable
[xml]$csharpProjectInfo = Get-Content ([IO.Path]::Combine($CSharpPath, '*.csproj'))
$TargetFrameworks = @(@($csharpProjectInfo.Project.PropertyGroup)[0].TargetFrameworks.Split(
';', [StringSplitOptions]::RemoveEmptyEntries))
$PSFramework = $TargetFrameworks[0]
$PSFramework = if ($IsCoreCLR) {
$TargetFrameworks[1]
}
else {
$TargetFrameworks[0]
}

task Clean {
if (Test-Path $ReleasePath) {
Expand Down Expand Up @@ -86,7 +91,7 @@ task CopyToRelease {
task Sign {
$vaultName = $env:AZURE_KEYVAULT_NAME
$vaultCert = $env:AZURE_KEYVAULT_CERT
if (-not $vaultName -or -not $vaultCert) {
if (-not $vaultName -or -not $vaultCert -or -not $IsCoreCLR) {
return
}

Expand Down
5 changes: 5 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ end {
$modulePath = [IO.Path]::Combine($PSScriptRoot, 'tools', 'Modules')
$requirements = Import-PowerShellDataFile ([IO.Path]::Combine($PSScriptRoot, 'requirements-dev.psd1'))
foreach ($req in $requirements.GetEnumerator()) {
# OpenAuthenticode only works for Pwsh 7+
if ($req.Key -eq 'OpenAuthenticode' -and -not $IsCoreCLR) {
continue
}

$targetPath = [IO.Path]::Combine($modulePath, $req.Key)

if (Test-Path -LiteralPath $targetPath) {
Expand Down
5 changes: 2 additions & 3 deletions module/Yayaml.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

# Script module or binary module file associated with this manifest.
RootModule = 'Yayaml.psm1'
# RootModule = 'bin/net6.0/Yayaml.dll'

# Version number of this module.
ModuleVersion = '0.3.0'
Expand All @@ -36,10 +35,10 @@
Description = 'Yet Another YAML parser and writer for PowerShell'

# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '7.2'
PowerShellVersion = '5.1'

# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = '4.7.2'
DotNetFrameworkVersion = '4.7.2'

# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# ClrVersion = '4.0'
Expand Down
44 changes: 31 additions & 13 deletions module/Yayaml.psm1
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
# Copyright: (c) 2023, Jordan Borean (@jborean93) <jborean93@gmail.com>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)

# This is used to load the shared assembly in the Default ALC which then sets
# an ALC for the moulde and any dependencies of that module to be loaded in
# that ALC.

$isReload = $true
if (-not ('Yayaml.LoadContext' -as [type])) {
$isReload = $false
$moduleName = [System.IO.Path]::GetFileNameWithoutExtension($PSCommandPath)
Add-Type -Path ([System.IO.Path]::Combine($PSScriptRoot, 'bin', 'net6.0', "$moduleName.dll"))
$importModule = Get-Command -Name Import-Module -Module Microsoft.PowerShell.Core
$moduleName = [System.IO.Path]::GetFileNameWithoutExtension($PSCommandPath)

if (-not $IsCoreClr) {
# PowerShell 5.1 has no concept of an Assembly Load Context so it will
# just load the module assembly directly.

$innerMod = if ('Yayaml.Module.NewYamlSchemaCommand' -as [type]) {
$modAssembly = [Yayaml.Module.NewYamlSchemaCommand].Assembly
&$importModule -Assembly $modAssembly -Force -PassThru
}
else {
$modPath = [System.IO.Path]::Combine($PSScriptRoot, 'bin', 'net472', "$moduleName.Module.dll")
&$importModule -Name $modPath -ErrorAction Stop -PassThru
}
}
else {
# This is used to load the shared assembly in the Default ALC which then sets
# an ALC for the moulde and any dependencies of that module to be loaded in
# that ALC.

$mainModule = [Yayaml.LoadContext]::Initialize()
$alcModule = Import-Module -Assembly $mainModule -PassThru
$isReload = $true
if (-not ('Yayaml.LoadContext' -as [type])) {
$isReload = $false

Add-Type -Path ([System.IO.Path]::Combine($PSScriptRoot, 'bin', 'net6.0', "$moduleName.dll"))
}

$mainModule = [Yayaml.LoadContext]::Initialize()
$innerMod = &$importModule -Assembly $mainModule -PassThru:$isReload
}

if ($isReload) {
if ($innerMod) {
# Bug in pwsh, Import-Module in an assembly will pick up a cached instance
# and not call the same path to set the nested module's cmdlets to the
# current module scope.
Expand All @@ -24,7 +42,7 @@ if ($isReload) {
'AddExportedCmdlet',
[System.Reflection.BindingFlags]'Instance, NonPublic'
)
foreach ($cmd in $alcModule.ExportedCommands.Values) {
foreach ($cmd in $innerMod.ExportedCommands.Values) {
$addExportedCmdlet.Invoke($ExecutionContext.SessionState.Module, @(, $cmd))
}
}
Expand Down
5 changes: 1 addition & 4 deletions src/Yayaml.Module/AddYamlFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ protected override void ProcessRecord()
return;
}

YayamlFormat format = new(
CollectionStyle: CollectionStyle,
ScalarStyle: ScalarStyle
);
YayamlFormat format = new(CollectionStyle, ScalarStyle);
InputObject.Properties.Add(new PSNoteProperty(SchemaHelpers.YAYAML_FORMAT_ID, format));

if (PassThru)
Expand Down
4 changes: 4 additions & 0 deletions src/Yayaml.Module/ConvertFromYaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public sealed class ConvertFromYamlCommand : PSCmdlet
public SwitchParameter NoEnumerate { get; set; }

[Parameter]
#if CORE
[YamlSchemaCompletions]
#else
[ArgumentCompleter(typeof(YamlSchemaCompletionsAttribute))]
#endif
[SchemaParameterTransformer]
public YamlSchema? Schema { get; set; }

Expand Down
6 changes: 5 additions & 1 deletion src/Yayaml.Module/ConvertToYaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ public sealed class ConvertToYamlCommand : PSCmdlet
public SwitchParameter IndentSequence { get; set; }

[Parameter]
#if CORE
[YamlSchemaCompletions]
#else
[ArgumentCompleter(typeof(YamlSchemaCompletionsAttribute))]
#endif
[SchemaParameterTransformer]
public YamlSchema? Schema { get; set; }

Expand Down Expand Up @@ -285,7 +289,7 @@ private YamlScalarNode GetScalarNode(ScalarValue value)
};
if (!string.IsNullOrWhiteSpace(value.Tag))
{
node.Tag = new(value.Tag);
node.Tag = new(value.Tag!);
}

return node;
Expand Down
4 changes: 4 additions & 0 deletions src/Yayaml.Module/NewYamlSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ public sealed class NewYamlSchemaCommand : PSCmdlet
public SequenceParser? ParseSequence { get; set; }

[Parameter]
#if CORE
[YamlSchemaCompletions]
#else
[ArgumentCompleter(typeof(YamlSchemaCompletionsAttribute))]
#endif
[SchemaParameterTransformer]
public YamlSchema? BaseSchema { get; set; }

Expand Down
44 changes: 38 additions & 6 deletions src/Yayaml.Module/ParameterHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,53 @@
using System.Collections;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Language;

namespace Yayaml.Module;

#if CORE
public class YamlSchemaCompletionsAttribute : ArgumentCompletionsAttribute
{
public YamlSchemaCompletionsAttribute()
: base(
"Blank",
"Yaml11",
"Yaml12",
"Yaml12JSON"
)
: base(SchemaParameterTransformer.KNOWN_SCHEMAS)
{ }
}
#else
public class YamlSchemaCompletionsAttribute : IArgumentCompleter {
public IEnumerable<CompletionResult> CompleteArgument(
string commandName,
string parameterName,
string wordToComplete,
CommandAst commandAst,
IDictionary fakeBoundParameters
)
{
if (string.IsNullOrWhiteSpace(wordToComplete))
{
wordToComplete = "";
}

WildcardPattern pattern = new($"{wordToComplete}*");
foreach (string encoding in SchemaParameterTransformer.KNOWN_SCHEMAS)
{
if (pattern.IsMatch(encoding))
{
yield return new CompletionResult(encoding);
}
}
}
}
#endif

public sealed class SchemaParameterTransformer : ArgumentTransformationAttribute
{
internal static string[] KNOWN_SCHEMAS = new[] {
"Blank",
"Yaml11",
"Yaml12",
"Yaml12JSON"
};

public override object Transform(EngineIntrinsics engineIntrinsics,
object? inputData)
{
Expand Down
4 changes: 3 additions & 1 deletion src/Yayaml.Module/ReflectionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ public static Array SpanToArray(object obj, PropertyInfo spanProp)
MethodInfo spanToArrayMeth = spanType.GetMethod(
"ToArray",
BindingFlags.Public | BindingFlags.Instance,
Array.Empty<Type>()
null,
Array.Empty<Type>(),
null
)!;

const string invokeMethName = "Invoke";
Expand Down
17 changes: 15 additions & 2 deletions src/Yayaml.Module/Yayaml.Module.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net472;net6.0</TargetFrameworks>
<LangVersion>10.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
<DefineConstants>$(DefineConstants);CORE</DefineConstants>
</PropertyGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
<PackageReference Include="System.Management.Automation" Version="7.2.0" PrivateAssets="all" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<PackageReference Include="PowerShellStandard.Library" Version="5.1.0" PrivateAssets="all" />
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="YamlDotNet" Version="13.7.1" />
<ProjectReference Include="../Yayaml/Yayaml.csproj" />
</ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/Yayaml/LoadContext.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#if CORE
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;

[assembly: InternalsVisibleTo("Yayaml.Module")]

namespace Yayaml;

public class LoadContext : AssemblyLoadContext
Expand Down Expand Up @@ -69,3 +68,4 @@ public static Assembly Initialize()
}
}
}
#endif
Loading