From 9e8f5bde3397700fc5c15337fd21c31a1de368b9 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Tue, 22 Jan 2019 21:43:47 +0000 Subject: [PATCH 1/8] Merged PR 6644: Update hosting tests and metadata.json for 6.2.0-preview.4 release Update hosting tests and metadata.json for 6.2.0-preview.4 release --- test/hosting/hosting.tests.csproj | 2 +- tools/metadata.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/hosting/hosting.tests.csproj b/test/hosting/hosting.tests.csproj index 2085e751c3..1762de2ad6 100644 --- a/test/hosting/hosting.tests.csproj +++ b/test/hosting/hosting.tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/tools/metadata.json b/tools/metadata.json index 841387ff45..525e062e90 100644 --- a/tools/metadata.json +++ b/tools/metadata.json @@ -1,7 +1,7 @@ { "StableReleaseTag": "v6.1.2", - "PreviewReleaseTag": "v6.2.0-preview.3", + "PreviewReleaseTag": "v6.2.0-preview.4", "ServicingReleaseTag": "v6.0.5", "ReleaseTag": "v6.1.2", - "NextReleaseTag": "v6.2.0-preview.3" + "NextReleaseTag": "v6.2.0-preview.4" } From 0dff846fe022f27fd64b3624e0031ddd6ee4ce87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 22 Jan 2019 14:35:36 -0800 Subject: [PATCH 2/8] Build(deps): Bump Microsoft.PowerShell.Native (#8712) --- .../System.Management.Automation.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/System.Management.Automation.csproj b/src/System.Management.Automation/System.Management.Automation.csproj index 314349379f..9fc0009eb8 100644 --- a/src/System.Management.Automation/System.Management.Automation.csproj +++ b/src/System.Management.Automation/System.Management.Automation.csproj @@ -23,7 +23,7 @@ - + From 7085d884539d3e20fff971662066e2ef21e5a4e1 Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 22 Jan 2019 17:09:39 -0800 Subject: [PATCH 3/8] Package validation tests updates (#8714) --- docker/tests/Templates/debian.8/Dockerfile | 28 ------------- docker/tests/Templates/fedora26/Dockerfile | 26 ------------ docker/tests/Templates/fedora27/Dockerfile | 26 ------------ .../Templates/fxdependent-debian.9/Dockerfile | 2 +- .../Templates/fxdependent-fedora27/Dockerfile | 38 ------------------ .../fxdependent-opensuse42.2/Dockerfile | 40 ------------------- .../fxdependent-opensuse42.3/Dockerfile | 3 +- .../fxdependent-ubuntu18.04/Dockerfile | 2 +- .../tests/Templates/opensuse42.2/Dockerfile | 39 ------------------ docker/tests/containerTestCommon.psm1 | 10 ----- 10 files changed, 4 insertions(+), 210 deletions(-) delete mode 100644 docker/tests/Templates/debian.8/Dockerfile delete mode 100644 docker/tests/Templates/fedora26/Dockerfile delete mode 100644 docker/tests/Templates/fedora27/Dockerfile delete mode 100644 docker/tests/Templates/fxdependent-fedora27/Dockerfile delete mode 100644 docker/tests/Templates/fxdependent-opensuse42.2/Dockerfile delete mode 100644 docker/tests/Templates/opensuse42.2/Dockerfile diff --git a/docker/tests/Templates/debian.8/Dockerfile b/docker/tests/Templates/debian.8/Dockerfile deleted file mode 100644 index 1c52c3b8a2..0000000000 --- a/docker/tests/Templates/debian.8/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM debian:jessie - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - apt-utils \ - ca-certificates \ - curl \ - apt-transport-https \ - locales \ - git - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN locale-gen $LANG && update-locale - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME -RUN dpkg -i $PACKAGENAME || : -RUN apt-get install -y -f -RUN $TESTDOWNLOADCOMMAND -RUN pwsh$PREVIEWSUFFIX -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fedora26/Dockerfile b/docker/tests/Templates/fedora26/Dockerfile deleted file mode 100644 index 25adfec102..0000000000 --- a/docker/tests/Templates/fedora26/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM fedora:26 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN dnf install -y \ - curl \ - glibc-locale-source \ - compat-openssl10 \ - git \ - && dnf upgrade-minimal -y --security \ - && dnf clean all - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME -RUN dnf install -y $PACKAGENAME -RUN $TESTDOWNLOADCOMMAND -RUN pwsh$PREVIEWSUFFIX -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fedora27/Dockerfile b/docker/tests/Templates/fedora27/Dockerfile deleted file mode 100644 index 78bf3595a4..0000000000 --- a/docker/tests/Templates/fedora27/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM fedora:27 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN dnf install -y \ - curl \ - glibc-locale-source \ - git \ - compat-openssl10 \ - && dnf upgrade-minimal -y --security \ - && dnf clean all - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME -RUN dnf install -y $PACKAGENAME -RUN $TESTDOWNLOADCOMMAND -RUN pwsh$PREVIEWSUFFIX -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-debian.9/Dockerfile b/docker/tests/Templates/fxdependent-debian.9/Dockerfile index e591a35aba..3c4b6815d5 100644 --- a/docker/tests/Templates/fxdependent-debian.9/Dockerfile +++ b/docker/tests/Templates/fxdependent-debian.9/Dockerfile @@ -1,4 +1,4 @@ -FROM microsoft/dotnet:2.1-runtime-stretch-slim +FROM microsoft/dotnet:2.1.7-runtime-stretch-slim ARG PACKAGENAME ARG PACKAGELOCATION diff --git a/docker/tests/Templates/fxdependent-fedora27/Dockerfile b/docker/tests/Templates/fxdependent-fedora27/Dockerfile deleted file mode 100644 index d96df77b4d..0000000000 --- a/docker/tests/Templates/fxdependent-fedora27/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM fedora:27 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN dnf install -y \ - glibc-locale-source \ - git \ - compat-openssl10 \ - && dnf upgrade-minimal -y --security \ - && dnf clean all - -# Install dotnet-runtime -RUN rpm --import https://packages.microsoft.com/keys/microsoft.asc -ADD https://packages.microsoft.com/config/fedora/27/prod.repo . -RUN mv prod.repo /etc/yum.repos.d/microsoft-prod.repo -RUN dnf install -y \ - dotnet-runtime-2.1 \ - && dnf upgrade-minimal -y --security \ - && dnf clean all - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -# Install PowerShell package -ADD $PACKAGELOCATION/$PACKAGENAME . -RUN mkdir -p /opt/microsoft/powershell -RUN tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Download and run tests -RUN $TESTDOWNLOADCOMMAND -RUN dotnet /opt/microsoft/powershell/pwsh.dll -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-opensuse42.2/Dockerfile b/docker/tests/Templates/fxdependent-opensuse42.2/Dockerfile deleted file mode 100644 index c38ff0e129..0000000000 --- a/docker/tests/Templates/fxdependent-opensuse42.2/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -FROM opensuse:42.2 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -# Install dependencies -RUN zypper --non-interactive update --skip-interactive \ - && zypper --non-interactive install \ - glibc-locale \ - glibc-i18ndata \ - tar \ - libunwind \ - libicu \ - openssl \ - git - -# Install dotnet-runtime -RUN rpm --import https://packages.microsoft.com/keys/microsoft.asc -ADD https://packages.microsoft.com/config/opensuse/42.2/prod.repo . -RUN mv prod.repo /etc/zypp/repos.d/microsoft-prod.repo -RUN zypper --non-interactive update --skip-interactive \ - && zypper --non-interactive install \ - dotnet-runtime-2.1 - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -# Install PowerShell package -ADD $PACKAGELOCATION/$PACKAGENAME . -RUN mkdir -p /opt/microsoft/powershell -RUN tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Download and run tests -RUN $TESTDOWNLOADCOMMAND -RUN dotnet /opt/microsoft/powershell/pwsh.dll -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/Templates/fxdependent-opensuse42.3/Dockerfile b/docker/tests/Templates/fxdependent-opensuse42.3/Dockerfile index f6122c9d53..74b4bc9825 100644 --- a/docker/tests/Templates/fxdependent-opensuse42.3/Dockerfile +++ b/docker/tests/Templates/fxdependent-opensuse42.3/Dockerfile @@ -18,7 +18,8 @@ RUN zypper --non-interactive update --skip-interactive \ git # Install dotnet-runtime -RUN rpm --import https://packages.microsoft.com/keys/microsoft.asc +ADD https://packages.microsoft.com/keys/microsoft.asc . +RUN rpmkeys --import microsoft.asc ADD https://packages.microsoft.com/config/opensuse/42.2/prod.repo . RUN mv prod.repo /etc/zypp/repos.d/microsoft-prod.repo RUN zypper --non-interactive update --skip-interactive \ diff --git a/docker/tests/Templates/fxdependent-ubuntu18.04/Dockerfile b/docker/tests/Templates/fxdependent-ubuntu18.04/Dockerfile index 7c73ab2906..a8d8ccca43 100644 --- a/docker/tests/Templates/fxdependent-ubuntu18.04/Dockerfile +++ b/docker/tests/Templates/fxdependent-ubuntu18.04/Dockerfile @@ -1,4 +1,4 @@ -FROM microsoft/dotnet:2.1-runtime-bionic +FROM microsoft/dotnet:2.1.7-runtime-bionic ARG PACKAGENAME ARG PACKAGELOCATION diff --git a/docker/tests/Templates/opensuse42.2/Dockerfile b/docker/tests/Templates/opensuse42.2/Dockerfile deleted file mode 100644 index 31c16d5927..0000000000 --- a/docker/tests/Templates/opensuse42.2/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM opensuse:42.2 - -ARG PACKAGENAME -ARG PACKAGELOCATION -ARG PREVIEWSUFFIX= -ARG TESTLIST=/PowerShell/test/powershell/Modules/PackageManagement/PackageManagement.Tests.ps1,/PowerShell/test/powershell/engine/Module -ARG TESTDOWNLOADCOMMAND="git clone --recursive https://github.com/PowerShell/PowerShell.git" - -ARG POWERSHELL_LINKFILE=/usr/bin/pwsh - -# Install dependencies -RUN zypper --non-interactive update --skip-interactive \ - && zypper --non-interactive install \ - glibc-locale \ - glibc-i18ndata \ - tar \ - curl \ - libunwind \ - libicu \ - openssl \ - git - -# Setup the locale -ENV LANG en_US.UTF-8 -ENV LC_ALL $LANG -RUN localedef --charmap=UTF-8 --inputfile=en_US $LANG - -RUN curl -L -o $PACKAGENAME $PACKAGELOCATION/$PACKAGENAME - -# Create the target folder where powershell will be placed -RUN mkdir -p /opt/microsoft/powershell -# Expand powershell to the target folder -RUN tar zxf $PACKAGENAME -C /opt/microsoft/powershell - -# Create the symbolic link that points to powershell -RUN ln -s /opt/microsoft/powershell/pwsh $POWERSHELL_LINKFILE - -RUN $TESTDOWNLOADCOMMAND -RUN pwsh -c "Import-Module /PowerShell/build.psm1;\$dir='/usr/local/share/powershell/Modules';\$null=New-Item -Type Directory -Path \$dir -ErrorAction SilentlyContinue;Restore-PSPester -Destination \$dir;exit (Invoke-Pester $TESTLIST -PassThru).FailedCount" diff --git a/docker/tests/containerTestCommon.psm1 b/docker/tests/containerTestCommon.psm1 index 76caafce98..75796c2fed 100644 --- a/docker/tests/containerTestCommon.psm1 +++ b/docker/tests/containerTestCommon.psm1 @@ -221,19 +221,14 @@ function Get-DefaultPreviewConfigForPackageValidation # format: = @{ 'centos7'='rhel.7'; 'debian.9'='debian.9'; - 'fedora26'='rhel.7'; - 'fedora27'='rhel.7'; 'fedora28'='rhel.7'; - 'opensuse42.2'='linux-x64.tar.gz'; 'opensuse42.3'='linux-x64.tar.gz'; 'ubuntu14.04'='ubuntu.14.04'; 'ubuntu16.04'='ubuntu.16.04'; 'ubuntu18.04'='ubuntu.18.04'; 'fxdependent-centos7'='linux-x64-fxdependent.tar.gz'; 'fxdependent-debian.9'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-fedora27'='linux-x64-fxdependent.tar.gz'; 'fxdependent-fedora28'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-opensuse42.2'='linux-x64-fxdependent.tar.gz'; 'fxdependent-opensuse42.3'='linux-x64-fxdependent.tar.gz'; 'fxdependent-ubuntu14.04'='linux-x64-fxdependent.tar.gz'; 'fxdependent-ubuntu16.04'='linux-x64-fxdependent.tar.gz'; @@ -250,16 +245,11 @@ function Get-DefaultStableConfigForPackageValidation # format: = @{ 'centos7'='rhel.7'; 'debian.9'='debian.9'; - 'fedora26'='rhel.7'; - 'fedora27'='rhel.7'; - 'opensuse42.2'='linux-x64.tar.gz'; 'opensuse42.3'='linux-x64.tar.gz'; 'ubuntu14.04'='ubuntu.14.04'; 'ubuntu16.04'='ubuntu.16.04'; 'fxdependent-centos7'='linux-x64-fxdependent.tar.gz'; 'fxdependent-debian.9'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-fedora27'='linux-x64-fxdependent.tar.gz'; - 'fxdependent-opensuse42.2'='linux-x64-fxdependent.tar.gz'; 'fxdependent-opensuse42.3'='linux-x64-fxdependent.tar.gz'; 'fxdependent-ubuntu14.04'='linux-x64-fxdependent.tar.gz'; 'fxdependent-ubuntu16.04'='linux-x64-fxdependent.tar.gz' From c4b2105a7314d9e69c9227027a82e5e5cca17c92 Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Wed, 23 Jan 2019 02:18:44 +0000 Subject: [PATCH 4/8] Merged PR 6648: Bump SDK and Runtime Versions Bump SDK and Runtime Versions - Also, fix alpine docker file - Also, fix extra files being added to some Modules after these changes --- PowerShell.Common.props | 2 +- assets/files.wxs | 16 ++++++++-------- build.psm1 | 8 ++++---- global.json | 2 +- test/Test.Common.props | 2 +- .../Modules/HelpersCommon/HelpersCommon.psm1 | 7 ++----- test/tools/WebListener/WebListener.csproj | 2 +- tools/packaging/packaging.psm1 | 2 +- .../microsoft_powershell_alpine3/Dockerfile | 4 ++-- 9 files changed, 21 insertions(+), 24 deletions(-) diff --git a/PowerShell.Common.props b/PowerShell.Common.props index d25ddac462..bb56e46894 100644 --- a/PowerShell.Common.props +++ b/PowerShell.Common.props @@ -94,7 +94,7 @@ (c) Microsoft Corporation. All rights reserved. netcoreapp2.1 - 2.1.5 + 2.1.7 Latest true diff --git a/assets/files.wxs b/assets/files.wxs index 9d8e96d07c..d51b85db35 100644 --- a/assets/files.wxs +++ b/assets/files.wxs @@ -1988,12 +1988,6 @@ - - - - - - @@ -2157,6 +2151,12 @@ + + + + + + @@ -2794,8 +2794,6 @@ - - @@ -2850,6 +2848,8 @@ + + diff --git a/build.psm1 b/build.psm1 index defaa2af59..b1c8dd6794 100644 --- a/build.psm1 +++ b/build.psm1 @@ -478,6 +478,9 @@ Fix steps: if ($CI) { Restore-PSPester -Destination (Join-Path $publishPath "Modules") } + + # Remove .nupkg.metadata files + Get-ChildItem $publishPath -Filter '.nupkg.metadata' -Recurse | ForEach-Object { Remove-Item $_.FullName -ErrorAction SilentlyContinue -Force } } function Restore-PSPackage @@ -1200,10 +1203,7 @@ function Publish-TestResults $resolvedPath = (Resolve-Path -Path $Path).ProviderPath Write-Host "##vso[results.publish type=$Type;mergeResults=true;runTitle=$Title;publishRunAttachments=true;resultFiles=$resolvedPath;]" - if($env:BUILD_REASON -ne 'PullRequest') - { - Write-Host "##vso[artifact.upload containerfolder=testResults;artifactname=testResults]$resolvedPath" - } + Write-Host "##vso[artifact.upload containerfolder=testResults;artifactname=testResults]$resolvedPath" } } diff --git a/global.json b/global.json index 55e448dfe0..05f4d3751c 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "2.1.403" + "version": "2.1.503" } } diff --git a/test/Test.Common.props b/test/Test.Common.props index 11b20a9fed..7a32a5c218 100644 --- a/test/Test.Common.props +++ b/test/Test.Common.props @@ -5,7 +5,7 @@ (c) Microsoft Corporation. All rights reserved. netcoreapp2.1 - 2.1.5 + 2.1.7 true true diff --git a/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 b/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 index 9879d32a24..c88916e1f9 100644 --- a/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 +++ b/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 @@ -233,11 +233,8 @@ function Send-VstsLogFile { Copy-Item -Path $Path -Destination $logFile } - if($env:BUILD_REASON -ne 'PullRequest') - { - Write-Host "##vso[artifact.upload containerfolder=$name;artifactname=$name]$logFile" - Write-Verbose "Log file captured as $name" -Verbose - } + Write-Host "##vso[artifact.upload containerfolder=$name;artifactname=$name]$logFile" + Write-Verbose "Log file captured as $name" -Verbose } # Tests if the Linux or macOS user is root diff --git a/test/tools/WebListener/WebListener.csproj b/test/tools/WebListener/WebListener.csproj index 92f576a57a..9c558815ed 100644 --- a/test/tools/WebListener/WebListener.csproj +++ b/test/tools/WebListener/WebListener.csproj @@ -7,7 +7,7 @@ - + diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index af179ecbf8..e9c4b84670 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -2792,7 +2792,7 @@ function Test-FileWxs Write-Warning -Message "Pushing MSI File fragment failed." } } - elseif ($env:TF_BUILD -and $env:BUILD_REASON -ne 'PullRequest') + elseif ($env:TF_BUILD) { Write-Host "##vso[artifact.upload containerfolder=wix;artifactname=wix]$newXmlFileName" } diff --git a/tools/releaseBuild/Images/microsoft_powershell_alpine3/Dockerfile b/tools/releaseBuild/Images/microsoft_powershell_alpine3/Dockerfile index af7ec8229b..c0541b7bbd 100644 --- a/tools/releaseBuild/Images/microsoft_powershell_alpine3/Dockerfile +++ b/tools/releaseBuild/Images/microsoft_powershell_alpine3/Dockerfile @@ -1,7 +1,7 @@ # Docker image file that describes an Centos7 image with PowerShell installed from Microsoft YUM Repo -FROM mcr.microsoft.com/powershell:6.1.0-alpine-3.8 -LABEL maintainer="PowerShell Team " +FROM mcr.microsoft.com/powershell:alpine-3.8 +LABEL maintainer="PowerShell Team " # Install dependencies and clean up RUN apk update \ From 9ceddc0dfef14e101ee4a5071c2bf8c6d724a179 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 23 Jan 2019 10:39:12 -0800 Subject: [PATCH 5/8] Refactor ConvertTo-Json to expose `JsonObject.ConvertToJson` as a public API (#8682) We have the public API `JsonObject.ConvertFromJson` to convert from JSON string in the PowerShell context. It would be good to have a public API for conversion to JSON. This PR refactors the `ConvertTo-Json` cmdlet to move the core implementation to `JsonObject.ConvertToJson`, and make `ConvertTo-Json` call that public method. This would help the Azure Function PowerShell worker. Currently, we depends on [calling the cmdlet](https://github.com/Azure/azure-functions-powershell-worker/blob/729710d2595b4b96abd4fa5a5547fe880e98bfa6/src/PowerShell/PowerShellManager.cs#L198-L205) to convert object to JSON which is expensive. Once we have the public method `JsonObject.ConvertToJson` exposed, we can call the API directly to avoid a command invocation. # Conflicts: # test/Test.Common.props --- .../utility/WebCmdlet/ConvertToJsonCommand.cs | 370 +-------------- .../commands/utility/WebCmdlet/JsonObject.cs | 436 +++++++++++++++++- test/Test.Common.props | 1 + test/xUnit/csharp/test_Utils.cs | 74 +++ 4 files changed, 534 insertions(+), 347 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs index d179a8c4fe..afdc300d71 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs @@ -2,22 +2,12 @@ // Licensed under the MIT License. using System; -using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Reflection; -using System.Text; -using Dbg = System.Management.Automation; using System.Management.Automation; using System.Management.Automation.Internal; - +using System.Threading; using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -// FxCop suppressions for resource strings: -[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "WebCmdletStrings.resources", MessageId = "json")] -[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "WebCmdletStrings.resources", MessageId = "Json")] namespace Microsoft.PowerShell.Commands { @@ -29,7 +19,6 @@ namespace Microsoft.PowerShell.Commands [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] public class ConvertToJsonCommand : PSCmdlet { - #region parameters /// /// Gets or sets the InputObject property. /// @@ -39,13 +28,18 @@ namespace Microsoft.PowerShell.Commands private int _depth = 2; private const int maxDepthAllowed = 100; + private readonly CancellationTokenSource cancellationSource = new CancellationTokenSource(); /// /// Gets or sets the Depth property. /// [Parameter] [ValidateRange(1, int.MaxValue)] - public int Depth { get { return _depth; } set { _depth = value; } } + public int Depth + { + get { return _depth; } + set { _depth = value; } + } /// /// Gets or sets the Compress property. @@ -82,10 +76,6 @@ namespace Microsoft.PowerShell.Commands [Parameter] public StringEscapeHandling EscapeHandling { get; set; } = StringEscapeHandling.Default; - #endregion parameters - - #region overrides - /// /// Prerequisite checks. /// @@ -105,7 +95,7 @@ namespace Microsoft.PowerShell.Commands private List _inputObjects = new List(); /// - /// Caching the input objects for the convertto-json command. + /// Caching the input objects for the command. /// protected override void ProcessRecord() { @@ -122,344 +112,32 @@ namespace Microsoft.PowerShell.Commands { if (_inputObjects.Count > 0) { - object objectToProcess = (_inputObjects.Count > 1 || AsArray) ? (_inputObjects.ToArray() as object) : (_inputObjects[0]); - // Pre-process the object so that it serializes the same, except that properties whose - // values cannot be evaluated are treated as having the value null. - object preprocessedObject = null; - try - { - preprocessedObject = ProcessValue(objectToProcess, 0); - } - catch (StoppingException) - { - return; - } + object objectToProcess = (_inputObjects.Count > 1 || AsArray) ? (_inputObjects.ToArray() as object) : _inputObjects[0]; - JsonSerializerSettings jsonSettings = new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.None, - MaxDepth = 1024, - StringEscapeHandling = EscapeHandling - }; - if (EnumsAsStrings) - { - jsonSettings.Converters.Add(new StringEnumConverter()); - } + var context = new JsonObject.ConvertToJsonContext( + Depth, + EnumsAsStrings.IsPresent, + Compress.IsPresent, + cancellationSource.Token, + EscapeHandling, + targetCmdlet: this); - if (!Compress) + // null is returned only if the pipeline is stopping (e.g. ctrl+c is signaled). + // in that case, we shouldn't write the null to the output pipe. + string output = JsonObject.ConvertToJson(objectToProcess, in context); + if (output != null) { - jsonSettings.Formatting = Formatting.Indented; + WriteObject(output); } - - string output = JsonConvert.SerializeObject(preprocessedObject, jsonSettings); - WriteObject(output); } } - #endregion overrides - /// - /// Return an alternate representation of the specified object that serializes the same JSON, except - /// that properties that cannot be evaluated are treated as having the value null. - /// Primitive types are returned verbatim. Aggregate types are processed recursively. + /// Process the Ctrl+C signal. /// - /// The object to be processed. - /// The current depth into the object graph. - /// An object suitable for serializing to JSON. - private object ProcessValue(object obj, int depth) + protected override void StopProcessing() { - if (Stopping) - { - throw new StoppingException(); - } - - PSObject pso = obj as PSObject; - - if (pso != null) - obj = pso.BaseObject; - - object rv = obj; - bool isPurePSObj = false; - bool isCustomObj = false; - - if (obj == null - || DBNull.Value.Equals(obj) - || obj is string - || obj is char - || obj is bool - || obj is DateTime - || obj is DateTimeOffset - || obj is Guid - || obj is Uri - || obj is double - || obj is float - || obj is decimal) - { - rv = obj; - } - else if (obj is Newtonsoft.Json.Linq.JObject jObject) - { - rv = jObject.ToObject>(); - } - else - { - TypeInfo t = obj.GetType().GetTypeInfo(); - - if (t.IsPrimitive) - { - rv = obj; - } - else if (t.IsEnum) - { - // Win8:378368 Enums based on System.Int64 or System.UInt64 are not JSON-serializable - // because JavaScript does not support the necessary precision. - Type enumUnderlyingType = Enum.GetUnderlyingType(obj.GetType()); - if (enumUnderlyingType.Equals(typeof(Int64)) || enumUnderlyingType.Equals(typeof(UInt64))) - { - rv = obj.ToString(); - } - else - { - rv = obj; - } - } - else - { - if (depth > Depth) - { - if (pso != null && pso.immediateBaseObjectIsEmpty) - { - // The obj is a pure PSObject, we convert the original PSObject to a string, - // instead of its base object in this case - rv = LanguagePrimitives.ConvertTo(pso, typeof(string), - CultureInfo.InvariantCulture); - isPurePSObj = true; - } - else - { - rv = LanguagePrimitives.ConvertTo(obj, typeof(String), - CultureInfo.InvariantCulture); - } - } - else - { - IDictionary dict = obj as IDictionary; - if (dict != null) - { - rv = ProcessDictionary(dict, depth); - } - else - { - IEnumerable enumerable = obj as IEnumerable; - if (enumerable != null) - { - rv = ProcessEnumerable(enumerable, depth); - } - else - { - rv = ProcessCustomObject(obj, depth); - isCustomObj = true; - } - } - } - } - } - - rv = AddPsProperties(pso, rv, depth, isPurePSObj, isCustomObj); - - return rv; + cancellationSource.Cancel(); } - - /// - /// Add to a base object any properties that might have been added to an object (via PSObject) through the Add-Member cmdlet. - /// - /// The containing PSObject, or null if the base object was not contained in a PSObject. - /// The base object that might have been decorated with additional properties. - /// The current depth into the object graph. - /// The processed object is a pure PSObject. - /// The processed object is a custom object. - /// - /// The original base object if no additional properties had been added, - /// otherwise a dictionary containing the value of the original base object in the "value" key - /// as well as the names and values of an additional properties. - /// - private object AddPsProperties(object psobj, object obj, int depth, bool isPurePSObj, bool isCustomObj) - { - PSObject pso = psobj as PSObject; - - if (pso == null) - return obj; - - // when isPurePSObj is true, the obj is guaranteed to be a string converted by LanguagePrimitives - if (isPurePSObj) - return obj; - - bool wasDictionary = true; - IDictionary dict = obj as IDictionary; - - if (dict == null) - { - wasDictionary = false; - dict = new Dictionary(); - dict.Add("value", obj); - } - - AppendPsProperties(pso, dict, depth, isCustomObj); - - if (wasDictionary == false && dict.Count == 1) - return obj; - - return dict; - } - - /// - /// Append to a dictionary any properties that might have been added to an object (via PSObject) through the Add-Member cmdlet. - /// If the passed in object is a custom object (not a simple object, not a dictionary, not a list, get processed in ProcessCustomObject method), - /// we also take Adapted properties into account. Otherwise, we only consider the Extended properties. - /// When the object is a pure PSObject, it also gets processed in "ProcessCustomObject" before reaching this method, so we will - /// iterate both extended and adapted properties for it. Since it's a pure PSObject, there will be no adapted properties. - /// - /// The containing PSObject, or null if the base object was not contained in a PSObject. - /// The dictionary to which any additional properties will be appended. - /// The current depth into the object graph. - /// The processed object is a custom object. - private void AppendPsProperties(PSObject psobj, IDictionary receiver, int depth, bool isCustomObject) - { - // serialize only Extended and Adapted properties.. - PSMemberInfoCollection srcPropertiesToSearch = - new PSMemberInfoIntegratingCollection(psobj, - isCustomObject ? PSObject.GetPropertyCollection(PSMemberViewTypes.Extended | PSMemberViewTypes.Adapted) : - PSObject.GetPropertyCollection(PSMemberViewTypes.Extended)); - - foreach (PSPropertyInfo prop in srcPropertiesToSearch) - { - object value = null; - try - { - value = prop.Value; - } - catch (Exception) - { - } - - if (!receiver.Contains(prop.Name)) - { - receiver[prop.Name] = ProcessValue(value, depth + 1); - } - } - } - - /// - /// Return an alternate representation of the specified dictionary that serializes the same JSON, except - /// that any contained properties that cannot be evaluated are treated as having the value null. - /// - /// - /// - /// - private object ProcessDictionary(IDictionary dict, int depth) - { - Dictionary result = new Dictionary(dict.Count); - - foreach (DictionaryEntry entry in dict) - { - string name = entry.Key as string; - if (name == null) - { - // use the error string that matches the message from JavaScriptSerializer - var exception = - new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, - WebCmdletStrings.NonStringKeyInDictionary, - dict.GetType().FullName)); - ThrowTerminatingError(new ErrorRecord(exception, "NonStringKeyInDictionary", ErrorCategory.InvalidOperation, dict)); - } - - result.Add(name, ProcessValue(entry.Value, depth + 1)); - } - - return result; - } - - /// - /// Return an alternate representation of the specified collection that serializes the same JSON, except - /// that any contained properties that cannot be evaluated are treated as having the value null. - /// - /// - /// - /// - private object ProcessEnumerable(IEnumerable enumerable, int depth) - { - List result = new List(); - - foreach (object o in enumerable) - { - result.Add(ProcessValue(o, depth + 1)); - } - - return result; - } - - /// - /// Return an alternate representation of the specified aggregate object that serializes the same JSON, except - /// that any contained properties that cannot be evaluated are treated as having the value null. - /// - /// The result is a dictionary in which all public fields and public gettable properties of the original object - /// are represented. If any exception occurs while retrieving the value of a field or property, that entity - /// is included in the output dictionary with a value of null. - /// - /// - /// - /// - private object ProcessCustomObject(object o, int depth) - { - Dictionary result = new Dictionary(); - Type t = o.GetType(); - - foreach (FieldInfo info in t.GetFields(BindingFlags.Public | BindingFlags.Instance)) - { - if (!info.IsDefined(typeof(T), true)) - { - object value; - try - { - value = info.GetValue(o); - } - catch (Exception) - { - value = null; - } - - result.Add(info.Name, ProcessValue(value, depth + 1)); - } - } - - foreach (PropertyInfo info2 in t.GetProperties(BindingFlags.Public | BindingFlags.Instance)) - { - if (!info2.IsDefined(typeof(T), true)) - { - MethodInfo getMethod = info2.GetGetMethod(); - if ((getMethod != null) && (getMethod.GetParameters().Length <= 0)) - { - object value; - try - { - value = getMethod.Invoke(o, new object[0]); - } - catch (Exception) - { - value = null; - } - - result.Add(info2.Name, ProcessValue(value, depth + 1)); - } - } - } - - return result; - } - - /// - /// Exception used for Stopping. - /// - private class StoppingException : System.Exception { } } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/JsonObject.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/JsonObject.cs index 5f341a77b2..784b8ad026 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/JsonObject.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/JsonObject.cs @@ -7,8 +7,11 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Management.Automation; +using System.Reflection; using System.Text.RegularExpressions; +using System.Threading; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; namespace Microsoft.PowerShell.Commands @@ -19,13 +22,90 @@ namespace Microsoft.PowerShell.Commands [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] public static class JsonObject { + #region HelperTypes + + /// + /// Context for convert-to-json operation. + /// + public readonly struct ConvertToJsonContext + { + /// + /// Gets the maximum depth for walking the object graph. + /// + public readonly int MaxDepth; + + /// + /// Gets the cancellation token. + /// + public readonly CancellationToken CancellationToken; + + /// + /// Gets the StringEscapeHandling setting. + /// + public readonly StringEscapeHandling StringEscapeHandling; + + /// + /// Gets the EnumsAsStrings setting. + /// + public readonly bool EnumsAsStrings; + + /// + /// Gets the CompressOutput setting. + /// + public readonly bool CompressOutput; + + /// + /// Gets the target cmdlet that is doing the convert-to-json operation. + /// + public readonly PSCmdlet Cmdlet; + + /// + /// Constructor of ConvertToJsonContext. + /// + public ConvertToJsonContext(int maxDepth, bool enumsAsStrings, bool compressOutput) + : this(maxDepth, enumsAsStrings, compressOutput, CancellationToken.None, StringEscapeHandling.Default, targetCmdlet: null) + { + } + + /// + /// Constructor of ConvertToJsonContext. + /// + public ConvertToJsonContext( + int maxDepth, + bool enumsAsStrings, + bool compressOutput, + CancellationToken cancellationToken, + StringEscapeHandling stringEscapeHandling, + PSCmdlet targetCmdlet) + { + this.MaxDepth = maxDepth; + this.CancellationToken = cancellationToken; + this.StringEscapeHandling = stringEscapeHandling; + this.EnumsAsStrings = enumsAsStrings; + this.CompressOutput = compressOutput; + this.Cmdlet = targetCmdlet; + } + } + private class DuplicateMemberHashSet : HashSet { - public DuplicateMemberHashSet(int capacity) : base(capacity, StringComparer.OrdinalIgnoreCase) + public DuplicateMemberHashSet(int capacity) + : base(capacity, StringComparer.OrdinalIgnoreCase) { } } + /// + /// Exception used for cancellation. + /// + private class StoppingException : System.Exception + { + } + + #endregion HelperTypes + + #region ConvertFromJson + /// /// Convert a Json string back to an object of type PSObject. /// @@ -79,6 +159,7 @@ namespace Microsoft.PowerShell.Commands input, new JsonSerializerSettings { + // This TypeNameHandling setting is required to be secure. TypeNameHandling = TypeNameHandling.None, MetadataPropertyHandling = MetadataPropertyHandling.Ignore, MaxDepth = 1024 @@ -340,5 +421,358 @@ namespace Microsoft.PowerShell.Commands return result; } + + #endregion ConvertFromJson + + #region ConvertToJson + + /// + /// Convert an object to JSON string. + /// + public static string ConvertToJson(object objectToProcess, in ConvertToJsonContext context) + { + try + { + // Pre-process the object so that it serializes the same, except that properties whose + // values cannot be evaluated are treated as having the value null. + object preprocessedObject = ProcessValue(objectToProcess, currentDepth: 0, in context); + var jsonSettings = new JsonSerializerSettings + { + // This TypeNameHandling setting is required to be secure. + TypeNameHandling = TypeNameHandling.None, + MaxDepth = 1024, + StringEscapeHandling = context.StringEscapeHandling + }; + + if (context.EnumsAsStrings) + { + jsonSettings.Converters.Add(new StringEnumConverter()); + } + + if (!context.CompressOutput) + { + jsonSettings.Formatting = Formatting.Indented; + } + + return JsonConvert.SerializeObject(preprocessedObject, jsonSettings); + } + catch (StoppingException) + { + return null; + } + } + + /// + /// Return an alternate representation of the specified object that serializes the same JSON, except + /// that properties that cannot be evaluated are treated as having the value null. + /// Primitive types are returned verbatim. Aggregate types are processed recursively. + /// + /// The object to be processed. + /// The current depth into the object graph. + /// The context to use for the convert-to-json operation. + /// An object suitable for serializing to JSON. + private static object ProcessValue(object obj, int currentDepth, in ConvertToJsonContext context) + { + if (context.CancellationToken.IsCancellationRequested) + { + throw new StoppingException(); + } + + PSObject pso = obj as PSObject; + + if (pso != null) + { + obj = pso.BaseObject; + } + + object rv = obj; + bool isPurePSObj = false; + bool isCustomObj = false; + + if (obj == null + || DBNull.Value.Equals(obj) + || obj is string + || obj is char + || obj is bool + || obj is DateTime + || obj is DateTimeOffset + || obj is Guid + || obj is Uri + || obj is double + || obj is float + || obj is decimal) + { + rv = obj; + } + else if (obj is Newtonsoft.Json.Linq.JObject jObject) + { + rv = jObject.ToObject>(); + } + else + { + Type t = obj.GetType(); + + if (t.IsPrimitive) + { + rv = obj; + } + else if (t.IsEnum) + { + // Win8:378368 Enums based on System.Int64 or System.UInt64 are not JSON-serializable + // because JavaScript does not support the necessary precision. + Type enumUnderlyingType = Enum.GetUnderlyingType(obj.GetType()); + if (enumUnderlyingType.Equals(typeof(Int64)) || enumUnderlyingType.Equals(typeof(UInt64))) + { + rv = obj.ToString(); + } + else + { + rv = obj; + } + } + else + { + if (currentDepth > context.MaxDepth) + { + if (pso != null && pso.immediateBaseObjectIsEmpty) + { + // The obj is a pure PSObject, we convert the original PSObject to a string, + // instead of its base object in this case + rv = LanguagePrimitives.ConvertTo(pso, typeof(string), + CultureInfo.InvariantCulture); + isPurePSObj = true; + } + else + { + rv = LanguagePrimitives.ConvertTo(obj, typeof(String), + CultureInfo.InvariantCulture); + } + } + else + { + IDictionary dict = obj as IDictionary; + if (dict != null) + { + rv = ProcessDictionary(dict, currentDepth, in context); + } + else + { + IEnumerable enumerable = obj as IEnumerable; + if (enumerable != null) + { + rv = ProcessEnumerable(enumerable, currentDepth, in context); + } + else + { + rv = ProcessCustomObject(obj, currentDepth, in context); + isCustomObj = true; + } + } + } + } + } + + rv = AddPsProperties(pso, rv, currentDepth, isPurePSObj, isCustomObj, in context); + + return rv; + } + + /// + /// Add to a base object any properties that might have been added to an object (via PSObject) through the Add-Member cmdlet. + /// + /// The containing PSObject, or null if the base object was not contained in a PSObject. + /// The base object that might have been decorated with additional properties. + /// The current depth into the object graph. + /// The processed object is a pure PSObject. + /// The processed object is a custom object. + /// The context for the operation. + /// + /// The original base object if no additional properties had been added, + /// otherwise a dictionary containing the value of the original base object in the "value" key + /// as well as the names and values of an additional properties. + /// + private static object AddPsProperties(object psObj, object obj, int depth, bool isPurePSObj, bool isCustomObj, in ConvertToJsonContext context) + { + PSObject pso = psObj as PSObject; + + if (pso == null) + { + return obj; + } + + // when isPurePSObj is true, the obj is guaranteed to be a string converted by LanguagePrimitives + if (isPurePSObj) + { + return obj; + } + + bool wasDictionary = true; + IDictionary dict = obj as IDictionary; + + if (dict == null) + { + wasDictionary = false; + dict = new Dictionary(); + dict.Add("value", obj); + } + + AppendPsProperties(pso, dict, depth, isCustomObj, in context); + + if (wasDictionary == false && dict.Count == 1) + { + return obj; + } + + return dict; + } + + /// + /// Append to a dictionary any properties that might have been added to an object (via PSObject) through the Add-Member cmdlet. + /// If the passed in object is a custom object (not a simple object, not a dictionary, not a list, get processed in ProcessCustomObject method), + /// we also take Adapted properties into account. Otherwise, we only consider the Extended properties. + /// When the object is a pure PSObject, it also gets processed in "ProcessCustomObject" before reaching this method, so we will + /// iterate both extended and adapted properties for it. Since it's a pure PSObject, there will be no adapted properties. + /// + /// The containing PSObject, or null if the base object was not contained in a PSObject. + /// The dictionary to which any additional properties will be appended. + /// The current depth into the object graph. + /// The processed object is a custom object. + /// The context for the operation. + private static void AppendPsProperties(PSObject psObj, IDictionary receiver, int depth, bool isCustomObject, in ConvertToJsonContext context) + { + // serialize only Extended and Adapted properties.. + PSMemberInfoCollection srcPropertiesToSearch = + new PSMemberInfoIntegratingCollection(psObj, + isCustomObject ? PSObject.GetPropertyCollection(PSMemberViewTypes.Extended | PSMemberViewTypes.Adapted) : + PSObject.GetPropertyCollection(PSMemberViewTypes.Extended)); + + foreach (PSPropertyInfo prop in srcPropertiesToSearch) + { + object value = null; + try + { + value = prop.Value; + } + catch (Exception) + { + } + + if (!receiver.Contains(prop.Name)) + { + receiver[prop.Name] = ProcessValue(value, depth + 1, in context); + } + } + } + + /// + /// Return an alternate representation of the specified dictionary that serializes the same JSON, except + /// that any contained properties that cannot be evaluated are treated as having the value null. + /// + private static object ProcessDictionary(IDictionary dict, int depth, in ConvertToJsonContext context) + { + Dictionary result = new Dictionary(dict.Count); + + foreach (DictionaryEntry entry in dict) + { + string name = entry.Key as string; + if (name == null) + { + // use the error string that matches the message from JavaScriptSerializer + string errorMsg = string.Format( + CultureInfo.CurrentCulture, + WebCmdletStrings.NonStringKeyInDictionary, + dict.GetType().FullName); + + var exception = new InvalidOperationException(errorMsg); + if (context.Cmdlet != null) + { + var errorRecord = new ErrorRecord(exception, "NonStringKeyInDictionary", ErrorCategory.InvalidOperation, dict); + context.Cmdlet.ThrowTerminatingError(errorRecord); + } + else + { + throw exception; + } + } + + result.Add(name, ProcessValue(entry.Value, depth + 1, in context)); + } + + return result; + } + + /// + /// Return an alternate representation of the specified collection that serializes the same JSON, except + /// that any contained properties that cannot be evaluated are treated as having the value null. + /// + private static object ProcessEnumerable(IEnumerable enumerable, int depth, in ConvertToJsonContext context) + { + List result = new List(); + + foreach (object o in enumerable) + { + result.Add(ProcessValue(o, depth + 1, in context)); + } + + return result; + } + + /// + /// Return an alternate representation of the specified aggregate object that serializes the same JSON, except + /// that any contained properties that cannot be evaluated are treated as having the value null. + /// + /// The result is a dictionary in which all public fields and public gettable properties of the original object + /// are represented. If any exception occurs while retrieving the value of a field or property, that entity + /// is included in the output dictionary with a value of null. + /// + private static object ProcessCustomObject(object o, int depth, in ConvertToJsonContext context) + { + Dictionary result = new Dictionary(); + Type t = o.GetType(); + + foreach (FieldInfo info in t.GetFields(BindingFlags.Public | BindingFlags.Instance)) + { + if (!info.IsDefined(typeof(T), true)) + { + object value; + try + { + value = info.GetValue(o); + } + catch (Exception) + { + value = null; + } + + result.Add(info.Name, ProcessValue(value, depth + 1, in context)); + } + } + + foreach (PropertyInfo info2 in t.GetProperties(BindingFlags.Public | BindingFlags.Instance)) + { + if (!info2.IsDefined(typeof(T), true)) + { + MethodInfo getMethod = info2.GetGetMethod(); + if ((getMethod != null) && (getMethod.GetParameters().Length <= 0)) + { + object value; + try + { + value = getMethod.Invoke(o, new object[0]); + } + catch (Exception) + { + value = null; + } + + result.Add(info2.Name, ProcessValue(value, depth + 1, in context)); + } + } + } + + return result; + } + + #endregion ConvertToJson } } diff --git a/test/Test.Common.props b/test/Test.Common.props index 7a32a5c218..dd5c967091 100644 --- a/test/Test.Common.props +++ b/test/Test.Common.props @@ -6,6 +6,7 @@ netcoreapp2.1 2.1.7 + Latest true true diff --git a/test/xUnit/csharp/test_Utils.cs b/test/xUnit/csharp/test_Utils.cs index 9d1aeb249b..2abe69d37d 100644 --- a/test/xUnit/csharp/test_Utils.cs +++ b/test/xUnit/csharp/test_Utils.cs @@ -2,9 +2,13 @@ // Licensed under the MIT License. using System; +using System.Collections; +using System.Collections.Specialized; using System.Management.Automation; using System.Management.Automation.Internal; +using System.Threading; using System.Reflection; +using Microsoft.PowerShell.Commands; using Xunit; namespace PSTests.Parallel @@ -72,5 +76,75 @@ namespace PSTests.Parallel Assert.Throws(() => boundedStack.Pop()); } + + [Fact] + public static void TestConvertToJsonBasic() + { + var context = new JsonObject.ConvertToJsonContext(maxDepth: 1, enumsAsStrings: false, compressOutput: true); + string expected = "{\"name\":\"req\",\"type\":\"http\"}"; + OrderedDictionary hash = new OrderedDictionary { + {"name", "req"}, + {"type", "http"} + }; + string json = JsonObject.ConvertToJson(hash, in context); + Assert.Equal(expected, json); + + hash.Add("self", hash); + json = JsonObject.ConvertToJson(hash, context); + expected = "{\"name\":\"req\",\"type\":\"http\",\"self\":{\"name\":\"req\",\"type\":\"http\",\"self\":\"System.Collections.Specialized.OrderedDictionary\"}}"; + Assert.Equal(expected, json); + } + + [Fact] + public static void TestConvertToJsonWithEnum() + { + var context = new JsonObject.ConvertToJsonContext(maxDepth: 1, enumsAsStrings: false, compressOutput: true); + string expected = "{\"type\":1}"; + Hashtable hash = new Hashtable { + {"type", CommandTypes.Alias} + }; + string json = JsonObject.ConvertToJson(hash, in context); + Assert.Equal(expected, json); + + context = new JsonObject.ConvertToJsonContext(maxDepth: 1, enumsAsStrings: true, compressOutput: true); + json = JsonObject.ConvertToJson(hash, in context); + expected = "{\"type\":\"Alias\"}"; + Assert.Equal(expected, json); + } + + [Fact] + public static void TestConvertToJsonWithoutCompress() + { + var context = new JsonObject.ConvertToJsonContext(maxDepth: 1, enumsAsStrings: true, compressOutput: false); + string expected = @"{ + ""type"": ""Alias"" +}"; + Hashtable hash = new Hashtable { + {"type", CommandTypes.Alias} + }; + string json = JsonObject.ConvertToJson(hash, in context); + Assert.Equal(expected, json); + } + + [Fact] + public static void TestConvertToJsonCancellation() + { + var source = new CancellationTokenSource(); + var context = new JsonObject.ConvertToJsonContext( + maxDepth: 1, + enumsAsStrings: true, + compressOutput: false, + source.Token, + Newtonsoft.Json.StringEscapeHandling.Default, + targetCmdlet: null); + + source.Cancel(); + Hashtable hash = new Hashtable { + {"type", CommandTypes.Alias} + }; + + string json = JsonObject.ConvertToJson(hash, in context); + Assert.Null(json); + } } } From cab8f2638617eddcc8885ee7ac11b6ba77a89e47 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 23 Jan 2019 11:42:32 -0800 Subject: [PATCH 6/8] Generate and deploy reference assembly for Microsoft.PowerShell.Commands.Utility.dll (#8716) Update `New-ReferenceAssembly` and `New-UnifiedNugetPackage` to generate reference assembly for `Microsoft.PowerShell.Commands.Utility.dll` and properly deploy it for `Microsoft.PowerShell.Commands.Utility` NuGet package and `Microsoft.PowerShell.SDK` NuGet package. An incremental step to fix, eventually, #8121 --- tools/packaging/packaging.psm1 | 243 +++++++++++++++++-------- tools/packaging/packaging.strings.psd1 | 44 ++++- 2 files changed, 207 insertions(+), 80 deletions(-) diff --git a/tools/packaging/packaging.psm1 b/tools/packaging/packaging.psm1 index e9c4b84670..f2495a3ccf 100644 --- a/tools/packaging/packaging.psm1 +++ b/tools/packaging/packaging.psm1 @@ -1553,7 +1553,6 @@ function New-UnifiedNugetPackage $SnkFilePath = "$RepoRoot\src\signing\visualstudiopublic.snk" New-ReferenceAssembly -linux64BinPath $linuxBinPath -RefAssemblyDestinationPath $refBinPath -RefAssemblyVersion $PackageVersion -SnkFilePath $SnkFilePath -GenAPIToolPath $GenAPIToolPath - $refBinFullName = Join-Path $refBinPath 'System.Management.Automation.dll' foreach ($file in $fileList) { @@ -1565,8 +1564,7 @@ function New-UnifiedNugetPackage #region ref $refFolder = New-Item (Join-Path $filePackageFolder.FullName 'ref/netstandard2.0') -ItemType Directory -Force - Copy-Item $refBinFullName -Destination $refFolder -Force - Write-Log "Copied file $refBinFullName to $refFolder" + CopyReferenceAssemblies -assemblyName $fileBaseName -refBinPath $refBinPath -refNugetPath $refFolder -assemblyFileList $fileList #endregion ref $packageRuntimesFolderPath = $packageRuntimesFolder.FullName @@ -1695,6 +1693,44 @@ function New-UnifiedNugetPackage } } +<# + Copy the generated reference assemblies to the 'ref/netstandard2.0' folder properly. + This is a helper function used by 'New-UnifiedNugetPackage' +#> +function CopyReferenceAssemblies +{ + param( + [string] $assemblyName, + [string] $refBinPath, + [string] $refNugetPath, + [string[]] $assemblyFileList + ) + + switch ($assemblyName) { + "Microsoft.PowerShell.Commands.Utility" { + $ref_Utility = Join-Path -Path $refBinPath -ChildPath Microsoft.PowerShell.Commands.Utility.dll + Copy-Item $ref_Utility -Destination $refNugetPath -Force + Write-Log "Copied file $ref_Utility to $refNugetPath" + } + + "Microsoft.PowerShell.SDK" { + foreach ($asmFileName in $assemblyFileList) { + $refFile = Join-Path -Path $refBinPath -ChildPath $asmFileName + if (Test-Path -Path $refFile) { + Copy-Item $refFile -Destination $refNugetPath -Force + Write-Log "Copied file $refFile to $refNugetPath" + } + } + } + + default { + $ref_SMA = Join-Path -Path $refBinPath -ChildPath System.Management.Automation.dll + Copy-Item $ref_SMA -Destination $refNugetPath -Force + Write-Log "Copied file $ref_SMA to $refNugetPath" + } + } +} + <# .SYNOPSIS Return the list of packages and versions used by a project @@ -1840,15 +1876,6 @@ function New-ReferenceAssembly throw "New-ReferenceAssembly can be only executed on Windows platform." } - $genAPIFolder = New-TempFolder - $smaProjectFolder = New-Item -Path "$genAPIFolder/System.Management.Automation" -ItemType Directory -Force - $smaCs = Join-Path $smaProjectFolder 'System.Management.Automation.cs' - $smaCsFiltered = Join-Path $smaProjectFolder 'System.Management.Automation_Filtered.cs' - - Write-Log "Working directory: $genAPIFolder." - - #region GenAPI - $genAPIExe = Get-ChildItem -Path "$GenAPIToolPath/*GenAPI.exe" -Recurse if (-not (Test-Path $genAPIExe)) @@ -1858,23 +1885,78 @@ function New-ReferenceAssembly Write-Log "GenAPI nuget package saved and expanded." - $linuxSMAPath = Join-Path $Linux64BinPath "System.Management.Automation.dll" + $genAPIFolder = New-TempFolder + $packagingStrings.NugetConfigFile | Out-File -FilePath "$genAPIFolder/Nuget.config" -Force + Write-Log "Working directory: $genAPIFolder." - if (-not (Test-Path $linuxSMAPath)) - { - throw "System.Management.Automation.dll was not found at: $Linux64BinPath" + $SMAReferenceAssembly = $null + $assemblyNames = @( + "System.Management.Automation", + "Microsoft.PowerShell.Commands.Utility" + ) + + foreach ($assemblyName in $assemblyNames) { + + $projectFolder = New-Item -Path "$genAPIFolder/$assemblyName" -ItemType Directory -Force + $generatedSource = Join-Path $projectFolder "$assemblyName.cs" + $filteredSource = Join-Path $projectFolder "${assemblyName}_Filtered.cs" + + $linuxDllPath = Join-Path $Linux64BinPath "$assemblyName.dll" + if (-not (Test-Path $linuxDllPath)) { + throw "$assemblyName.dll was not found at: $Linux64BinPath" + } + + $genAPIArgs = "$linuxDllPath","-libPath:$Linux64BinPath" + Write-Log "GenAPI cmd: $genAPIExe $genAPIArgsString" + + Start-NativeExecution { & $genAPIExe $genAPIArgs } | Out-File $generatedSource -Force + Write-Log "Reference assembly file generated at: $generatedSource" + + CleanupGeneratedSourceCode -assemblyName $assemblyName -generatedSource $generatedSource -filteredSource $filteredSource + + try + { + Push-Location $projectFolder + + $csProj = GenerateCSProjectContent -AssemblyName $assemblyName -RefAssemblyVersion $RefAssemblyVersion -SnkFilePath $SnkFilePath -SMAReferencePath $SMAReferenceAssembly + $csProj | Out-File -FilePath "$projectFolder/$assemblyName.csproj" -Force + + Write-Host "##vso[artifact.upload containerfolder=artifact;artifactname=artifact]$projectFolder/$assemblyName.csproj" + Write-Host "##vso[artifact.upload containerfolder=artifact;artifactname=artifact]$generatedSource" + + Start-NativeExecution { dotnet build -c Release } + + $refBinPath = Join-Path $projectFolder "bin/Release/netstandard2.0/$assemblyName.dll" + if ($null -eq $refBinPath) { + throw "Reference assembly was not built." + } + + Copy-Item $refBinPath $RefAssemblyDestinationPath -Force + Write-Log "Reference assembly '$assemblyName.dll' built and copied to $RefAssemblyDestinationPath" + + if ($assemblyName -eq "System.Management.Automation") { + $SMAReferenceAssembly = $refBinPath + } + } + finally + { + Pop-Location + } } - $genAPIArgs = "$linuxSMAPath","-libPath:$Linux64BinPath" - Write-Log "GenAPI cmd: $genAPIExe $genAPIArgsString" + if (Test-Path $genAPIFolder) + { + Remove-Item $genAPIFolder -Recurse -Force -ErrorAction SilentlyContinue + } +} - Start-NativeExecution { & $genAPIExe $genAPIArgs } | Out-File $smaCs -Force - - Write-Log "Reference assembly file generated at: $smaCs" - - #endregion GenAPI - - #region Cleanup SMA.cs +function CleanupGeneratedSourceCode +{ + param( + [string] $assemblyName, + [string] $generatedSource, + [string] $filteredSource + ) $patternsToRemove = @( '[System.Management.Automation.ArgumentToEncodingTransformationAttribute]' @@ -1888,78 +1970,93 @@ function New-ReferenceAssembly 'typeof(System.Management.Automation.LanguagePrimitives.EnumMultipleTypeConverter)' '[System.Management.Automation.Internal.CommonParameters.ValidateVariableName]' '[System.Management.Automation.ArgumentEncodingCompletionsAttribute]' + '[Microsoft.PowerShell.Commands.AddMemberCommand' + '[System.Management.Automation.ArgumentCompleterAttribute(typeof(Microsoft.PowerShell.Commands.Utility.JoinItemCompleter))]' + '[System.Management.Automation.ArgumentCompleterAttribute(typeof(System.Management.Automation.PropertyNameCompleter))]' + '[System.Management.Automation.OutputTypeAttribute(typeof(Microsoft.PowerShell.MarkdownRender' + '[Microsoft.PowerShell.Commands.ArgumentToTypeNameTransformationAttribute]' + '[System.Management.Automation.Internal.ArchitectureSensitiveAttribute]' + '[Microsoft.PowerShell.Commands.SelectStringCommand.FileinfoToStringAttribute]' + '[System.Runtime.CompilerServices.IsReadOnlyAttribute]' ) - $reader = [System.IO.File]::OpenText($smaCs) - $writer = [System.IO.File]::CreateText($smaCsFiltered) + $patternsToReplace = @( + @{ + ApplyTo = "Microsoft.PowerShell.Commands.Utility" + Pattern = "[System.Runtime.CompilerServices.IsReadOnlyAttribute]ref Microsoft.PowerShell.Commands.JsonObject.ConvertToJsonContext" + Replacement = "in Microsoft.PowerShell.Commands.JsonObject.ConvertToJsonContext" + }, + @{ + ApplyTo = "Microsoft.PowerShell.Commands.Utility" + Pattern = "public partial struct ConvertToJsonContext" + Replacement = "public readonly struct ConvertToJsonContext" + } + ) + + $reader = [System.IO.File]::OpenText($generatedSource) + $writer = [System.IO.File]::CreateText($filteredSource) while($null -ne ($line = $reader.ReadLine())) { - $match = $line | Select-String -Pattern $patternsToRemove -SimpleMatch + $lineWasProcessed = $false + foreach ($patternToReplace in $patternsToReplace) + { + if ($assemblyName -eq $patternToReplace.ApplyTo -and $line.Contains($patternToReplace.Pattern)) { + $line = $line.Replace($patternToReplace.Pattern, $patternToReplace.Replacement) + $lineWasProcessed = $true + break + } + } - if ($null -ne $match) - { - $writer.WriteLine("//$line") - } - else - { - $writer.WriteLine($line) + if (!$lineWasProcessed) { + $match = Select-String -InputObject $line -Pattern $patternsToRemove -SimpleMatch + if ($null -ne $match) + { + $line = "//$line" + } } + + $writer.WriteLine($line) } + if ($null -ne $reader) { $reader.Close() } + if ($null -ne $writer) { $writer.Close() } - Move-Item $smaCsFiltered $smaCs -Force + Move-Item $filteredSource $generatedSource -Force + Write-Log "Code cleanup complete for reference assembly '$assemblyName'." +} - Write-Log "Reference assembly code cleanup complete." +function GenerateCSProjectContent +{ + param( + [string] $AssemblyName, + [string] $RefAssemblyVersion, + [string] $SnkFilePath, + [string] $SMAReferencePath + ) - #endregion Cleanup SMA.cs - - #region Build SMA ref assembly - - try - { - Push-Location $smaProjectFolder - - $csProj = $packagingStrings.RefAssemblyCsProj -f $RefAssemblyVersion,$SnkFilePath - - $csProj | Out-File -FilePath "$smaProjectFolder/System.Management.Automation.csproj" -Force - - Write-Host "##vso[artifact.upload containerfolder=artifact;artifactname=artifact]$smaProjectFolder/System.Management.Automation.csproj" - Write-Host "##vso[artifact.upload containerfolder=artifact;artifactname=artifact]$smaCs" - - $packagingStrings.NugetConfigFile | Out-File -FilePath "$genAPIFolder/Nuget.config" -Force - - Start-NativeExecution { dotnet build -c Release } - - $refBinPath = Join-Path $smaProjectFolder 'bin/Release/netstandard2.0/System.Management.Automation.dll' - - if ($null -eq $refBinPath) - { - throw "Reference assembly was not built." + switch ($assemblyName) { + "System.Management.Automation" { + $csProj = $packagingStrings.'System.Management.Automation' -f $RefAssemblyVersion, $SnkFilePath } - Copy-Item $refBinPath $RefAssemblyDestinationPath -Force + "Microsoft.PowerShell.Commands.Utility" { + $csProj = $packagingStrings.'Microsoft.PowerShell.Commands.Utility' -f $RefAssemblyVersion, $SnkFilePath, $SMAReferencePath + } - Write-Log "Reference assembly built and copied to $RefAssemblyDestinationPath" - } - finally - { - Pop-Location + default { + throw "It's not yet supported to generate reference assembly for '$assemblyName'" + } } - if (Test-Path $genAPIFolder) - { - Remove-Item $genAPIFolder -Recurse -Force -ErrorAction SilentlyContinue - } - - #endregion Build SMA ref assembly + return $csProj } <# diff --git a/tools/packaging/packaging.strings.psd1 b/tools/packaging/packaging.strings.psd1 index 1e862b5885..0b9209ec4c 100644 --- a/tools/packaging/packaging.strings.psd1 +++ b/tools/packaging/packaging.strings.psd1 @@ -39,6 +39,7 @@ case "$1" in ;; esac '@ + UbuntuAfterRemoveScript = @' #!/bin/sh set -e @@ -48,11 +49,13 @@ case "$1" in ;; esac '@ + MacOSLauncherScript = @' #!/usr/bin/env bash open {0} '@ -MacOSLauncherPlistTemplate = @' + + MacOSLauncherPlistTemplate = @' @@ -82,8 +85,9 @@ MacOSLauncherPlistTemplate = @' '@ -# see https://developer.apple.com/library/content/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html -OsxDistributionTemplate = @' + + # see https://developer.apple.com/library/content/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html + OsxDistributionTemplate = @' {0} @@ -107,7 +111,8 @@ OsxDistributionTemplate = @' {2} '@ -NuspecTemplate = @' + + NuspecTemplate = @' @@ -132,7 +137,8 @@ NuspecTemplate = @' '@ -RefAssemblyCsProj = @' + + 'System.Management.Automation' = @' netstandard2.0 @@ -140,15 +146,39 @@ RefAssemblyCsProj = @' true {1} true + Latest - + '@ -NuGetConfigFile = @' + + 'Microsoft.PowerShell.Commands.Utility' = @' + + + netstandard2.0 + {0} + true + {1} + true + Latest + + + + {2} + + + + + + + +'@ + + NuGetConfigFile = @' From ea0b4de90a4d807a9e40e8480bbb92a476f67ab2 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Thu, 10 Jan 2019 00:12:40 +0000 Subject: [PATCH 7/8] Merged PR 6442: Moved the cleanup logic to Restore-PSModuleToBuild Moved the cleanup logic to Restore-PSModuleToBuild # Conflicts: # build.psm1 --- build.psm1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.psm1 b/build.psm1 index b1c8dd6794..613303e0df 100644 --- a/build.psm1 +++ b/build.psm1 @@ -478,9 +478,6 @@ Fix steps: if ($CI) { Restore-PSPester -Destination (Join-Path $publishPath "Modules") } - - # Remove .nupkg.metadata files - Get-ChildItem $publishPath -Filter '.nupkg.metadata' -Recurse | ForEach-Object { Remove-Item $_.FullName -ErrorAction SilentlyContinue -Force } } function Restore-PSPackage @@ -556,6 +553,9 @@ function Restore-PSModuleToBuild Write-Log "Restore PowerShell modules to $publishPath" $modulesDir = Join-Path -Path $publishPath -ChildPath "Modules" Copy-PSGalleryModules -Destination $modulesDir -CsProjPath "$PSScriptRoot\src\Modules\PSGalleryModules.csproj" + + # Remove .nupkg.metadata files + Get-ChildItem $PublishPath -Filter '.nupkg.metadata' -Recurse | ForEach-Object { Remove-Item $_.FullName -ErrorAction SilentlyContinue -Force } } function Restore-PSPester From 9acd174225a00df4236e0c40183575c50b4cf4b4 Mon Sep 17 00:00:00 2001 From: Paul Higinbotham Date: Fri, 25 Jan 2019 18:24:38 +0000 Subject: [PATCH 8/8] Merged PR 6702: Add change log for v6.2.0-preview.4 release Add change log for v6.2.0-preview.4 release --- .spelling | 17 +++++ CHANGELOG.md | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 189 insertions(+), 1 deletion(-) diff --git a/.spelling b/.spelling index bba8203802..ade716e5a0 100644 --- a/.spelling +++ b/.spelling @@ -49,6 +49,7 @@ arm64 asp.net assemblyloadcontext authenticodesignature +azdevops azurerm.netcore.preview azurerm.profile.netcore.preview azurerm.resources.netcore.preview @@ -152,6 +153,7 @@ dchristian3188 ddwr debughandler dee-see +deps deserialization deserialize dest @@ -276,6 +278,7 @@ gitcommitid github githug gitter +glachancecmaisonneuve globbing GoogleTest gzip @@ -337,6 +340,7 @@ json jsonconfigfileaccessor judgement jumplist +jwmoss kanjibates kasper3 katacoda @@ -360,6 +364,7 @@ lee303 libpsl libpsl-native libunwind8 +linux locationglobber loopback lossless @@ -371,6 +376,7 @@ macos maertendmsft mahawar markekraus +marktiedemann mcbobke md meir017 @@ -447,6 +453,7 @@ non-r2 noresume notcontains nuget +nugetfeed nuget.exe numberbytes nupkg @@ -480,6 +487,7 @@ plaintext pluggable pluralsight poshcode +pougetat powerbi powercode powershell @@ -511,10 +519,12 @@ preview.4 preview1-24530-04 productversion program.cs +prototyyppi providername proxycommand ps1 ps1xml +pscore pscredential psd1 psdrive @@ -604,6 +614,7 @@ savehelp sazonov schvartzman schwartzmeyer +scriptblock securestring seemethere select-xml @@ -656,6 +667,7 @@ sudo superproject swarfegagit sxs +sydneyhsmith symlink symlinks syscall @@ -698,6 +710,8 @@ typecataloggen typeconversion typegen typematch +ubuntu +unicode unregister-event unregister-packagesource unregister-psrepository @@ -708,6 +722,7 @@ update-modulemanifest update-scriptfileinfo update-typedata uri +urls userdata uservoice utf8 @@ -772,7 +787,9 @@ www.github.com x64 x86 xpath +xtqqczze xunit +yaml youtube zackjknight vexx32 diff --git a/CHANGELOG.md b/CHANGELOG.md index fc70f6d4dc..5e51ed064a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,176 @@ # Changelog +## v6.2.0-preview.4 - 2019-01-28 + +### Breaking Changes +- Add `-Stable` to `Sort-Object` and related tests (#7862) (Thanks @KirkMunro!) +- Improve `Start-Sleep` cmdlet to accept fractional seconds (#8537) (Thanks @Prototyyppi!) +- Change hashtable to use `OrdinalIgnoreCase` to be case-insensitive in all Cultures (#8566) +- Fix `LiteralPath` in `Import-Csv` to bind to `Get-ChildItem` output (#8277) (Thanks @iSazonov!) + +### Engine Updates and Fixes +- Allow user-specified underlying type for enums (#8329) (Thanks @IISResetMe!) +- Handle case where AppLocker test script fails to delete (#8627) +- Update `CommandNotFound` fuzzy suggestion to only return unique results (#8640) +- Add support to show suggestions on `CommandNotFound` exception (#8458) +- Make `S.M.A.PowerShell.GetSteppablePipeline` method public (#8055) (Thanks @KirkMunro!) +- Add `S.M.A.PowerShell.Create` method overload with Runspace argument (#8057) (Thanks @KirkMunro!) +- Fix mistake on deserialization (#8502) +- Fix formatting of header of table when center aligned (#8497) +- Add `-RepeatHeader` to `Format-Table` to enable repeating header for each screen full (#8481) +- Fix `Debug-Runspace` for Unix platforms and properly enable Windows identity impersonation code (#8451) +- Reset output attributes if column had `ESC` char when using `Format-Table`; Replace `...` with unicode ellipsis (#8326) + +### Experimental Features +- Add the experimental feature `PSUseAbbreviationExpansion` to support tab completion on abbreviated command names (#8109) + +### General Cmdlet Updates and Fixes +- Fix code page parsing issue in `Invoke-RestMethod` (#8694) (Thanks @markekraus!) +- Fix `Expect 100-continue` issue with Web Cmdlets (#8679) (Thanks @markekraus!) +- Allow 'name' as an alias key for 'label' in `ConvertTo-Html`, allow the 'width' entry to be an integer (#8426) (Thanks @mklement0!) +- Resolve `:PAGER` if its path contains spaces (#8571) (Thanks @pougetat!) +- Add support enum and char types in `Format-Hex` cmdlet (#8191) (Thanks @iSazonov!) +- Change `Get-Help` cmdlet `-Parameter` parameter so it accepts string arrays (#8454) (Thanks @sethvs!) +- Fix `FixupFileName` to not load resolved assembly during module discovery (#8634) +- Change `Clear-Host` back to using `$RAWUI` and `clear` to work over remoting (#8609) +- Fix `LiteralPath` in `Import-Csv` to bind to `Get-ChildItem` output (#8277) (Thanks @iSazonov!) +- Make scriptblock based calculated properties work again in `ConvertTo-Html` (#8427) (Thanks @mklement0!) +- Fix `Join-String` cmdlet `FormatString` parameter logic (#8449) (Thanks @sethvs!) +- Allow Windows users in developer mode to create symlinks without elevation (#8534) +- `Help` function should only pass content to pager if content was found (#8528) +- Change `Clear-Host` to simply called `[console]::clear` and remove `clear` alias from Unix (#8603) +- `help` function shouldn't use pager for `AliasHelpInfo` (#8552) +- Fix XML nesting bug in `CustomSerializer.WriteMemberInfoCollection()` (#8476) (Thanks @IISResetMe!) +- Add `-UseMinimalHeader` to `Start-Transcript` to minimize transcript header (#8402) (Thanks @lukexjeremy!) + +### Code Cleanup +- Remove the no longer used `RunspaceConfigurationEntry` types (#8424) +- Remove unneeded catch/throw from `mkdir` and `oss` functions (#8425) +- Remove comments after closing brackets (#8344) (Thanks @Meir017!) +- Cleanup `Format-Hex` (#8683) (Thanks @vexx32!) +- Delete `appveyor.yml` (#8639) (Thanks @RDIL!) +- Revise use of `Start-Sleep` cmdlet (#8633) (Thanks @xtqqczze!) +- Style: Change first char to upper in summary comments (#8597) (Thanks @iSazonov!) +- Style: Use the type aliases `char` and `bool` instead of `Char` and `Boolean` (#8572) (Thanks @iSazonov!) +- Style: Use the type alias `string` instead of `String` in places that are appropriate (#8573) (Thanks @iSazonov!) +- Correctly capitalize the `ForEach` operator in `*.ps1` (#8583) (Thanks @xtqqczze!) +- Remove unnecessary trim of passed-in command line in interactive debugging (#8594) +- Style: Add a space after "//" in comments and remove unneeded comments after "}" (#8576) (Thanks @iSazonov!) +- Style: Add the ending period to the XML document texts (#8577) (Thanks @iSazonov!) +- Avoid use of `mkdir` alias in `*.ps1` and `*.psm1` (#8582) (Thanks @xtqqczze!) +- Regularize redirection operator spacing in `*.ps1` and `*.psm1` (#8581) (Thanks @xtqqczze!) +- Style: Change 'String.' to 'string.' (#8568) (Thanks @iSazonov!) +- Style: Replace `String.IsNullOrEmpty` with `string.IsNullOrEmpty` (#8557) (Thanks @iSazonov!) +- Fix typo in AMSI test (#8561) (Thanks @iSazonov!) +- Style: Convert to upper first char in `` and `` doc tags (#8556) (Thanks @iSazonov!) +- Style: Add period before `` and `` doc tags (#8553) (Thanks @iSazonov!) +- Remove use of cmdlet aliases from `.\test\powershell` (#8546) (Thanks @xtqqczze!) +- Style: Remove extra spaces after `` and before `` docs tags (#8547) (Thanks @iSazonov!) +- Style: Remove preceding spaces from C# `preprocessor-type` keywords (#8540) (Thanks @xtqqczze!) +- Style: remove ` ` (#8538) (Thanks @iSazonov!) +- Style: Add period before returns doc tag (#8535) (Thanks @iSazonov!) +- Style: Change `Object[]` to `object[]` (#8526) (Thanks @iSazonov!) +- Style: Change `Object` to `object` (#8522) (Thanks @iSazonov!) +- Style: Change `UInt64?` to `ulong?` (#8527) (Thanks @iSazonov!) +- Style: Change `Byte{}` to `byte[]` (#8525) (Thanks @iSazonov!) +- Code cleanup: Add space after closing brace where needed (#8530) +- Style: Change `System.Boolean` to `bool` (#8521) (Thanks @iSazonov!) +- Change `String` to `string` for simple references (#8519) +- Change `Int32` to `int` for simple references in variable declaration (#8518) +- Style: Member access symbols should be followed with member name (#8517) +- Style: Remove extra space before colon in named parameters (#8504) +- Style: Use the shorthand of the `nullable` type (#8501) +- Remove empty lines; correct space on closing square brackets, negative signs, and generic brackets (#8508) +- Remove space after new keyword in implicitly typed array allocation (#8505) +- The static keyword should be right after access modifier (#8506) +- Remove comments after closing bracket (#8503) +- Remove space character after `'!'` (#8507) +- Style: Remove extra space before colon in named parameters (#8504) + +### Tools +- Recommend Azure DevOps extension inside VS-Code for better `YAML` editing. (#8403) (Thanks @bergmeister!) +- `-AddToPath` re-implementation in `install-powershell.ps1` (#8081) (Thanks @glachancecmaisonneuve!) +- Change the feed `URL` to feed name due to changes in `AzDevOps` (#8664) +- Batch merge builds together while a merge build is running (#8668) +- Fix grammar in stale bot message (#8660) (Thanks @RDIL!) +- Add macOS files to `.gitignore` (#8456) (Thanks @RDIL!) +- Name the spelling yaml something more appropriate (#8601) (Thanks @RDIL!) +- Add script to create `icns` files. (#7456) (Thanks @thezim!) +- Pass `nugetkey` as parameter (#8461) +- Add `gitkracken` files to `gitignore` (#8434) (Thanks @RDIL!) +- Create release process issue template (#8417) +- Support for `linuxmint` in `installpsh-debian.sh` (#8440) (Thanks @DarwinJS!) +- Enable `install-powershell.ps1` to use `MSI` (#8418) + +### Tests +- Remove broken `HelpUri` from `CimTest` (#8688) (Thanks @xtqqczze!) +- Remove appveyor environment checks (#8669) (Thanks @RDIL!) +- Adding tests for `PSDiagnostics Module` (#8431) (Thanks @kvprasoon!) +- Increase diagnose-ability of Link Checker failures (#8667) +- Fix broken urls (#8653) +- Update fuzzy test to fix daily build (#8629) +- Create link check task (#8471) (Thanks @RDIL!) +- Add Tests for `ConfirmImpact` Ratings (#8214) (Thanks @vexx32!) +- Fix style issues in xUnit tests (#8465) (Thanks @iSazonov!) +- Move `xUnit` tests in new folder (#8356) (Thanks @iSazonov!) +- Fix environment variable test and add missing null check in `CommandHelpProvider` (#8408) +- Remove `dotnet` dependency to start WebListener (#8390) + +### Build and Packaging Improvements +- Update Third Party Notices (#8415) +- Adding yaml for Windows Release builds (#8374) +- Bump `NJsonSchema` from `9.13.1` to `9.13.2` (#8422) +- Do not ship fullclr binaries of `PackageManagement` (#8700) (Thanks @bergmeister!) +- Fix the build for `fxdependent` build for `dotnet sdk` (#8670) +- Add Windows build to universal release build YAML (#8695) +- Remove `Debian 8` references as it is EOL (#8678) +- Build(deps): Bump `NJsonSchema` from `9.13.14` to `9.13.15` (#8671) +- Build package build using ubuntu 18.04 image (#8666) +- Fix a typo in `packaging.psm1` (#8647) (Thanks @sethvs!) +- Add function to create a framework dependent package `dotnet-sdk` containers (#8644) +- Build(deps): Bump `NJsonSchema` from `9.13.13` to `9.13.14` (#8648) +- Build(deps): Bump `PowerShellGet` from `2.0.3` to `2.0.4` (#8649) +- Fix installing `fpm` and `ronn` in macOS CI by avoid installing docs for them (#8656) +- Build(deps): Bump `Markdig.Signed` from `0.15.6` to `0.15.7` (#8637) +- Build(deps): Bump `System.Security.Cryptography.Pkcs` from `4.5.1` to `4.5.2` (#8614) +- Build(deps): Bump `System.Net.Http.WinHttpHandler` from `4.5.1` to `4.5.2` (#8615) +- Build(deps): Bump `NJsonSchema` from `9.13.11` to `9.13.13` (#8616) +- Build(deps): Bump `System.Text.Encoding.CodePages` from `4.5.0` to `4.5.1` (#8613) +- Enable install of Preview MSI release side-by-side with Stable release (#8513) +- Get macOS to publish daily build to nugetfeed (#8464) +- Build(deps): Bump `Markdig.Signed` from `0.15.5` to `0.15.6` (#8558) +- Build(deps): Bump `NJsonSchema` from `9.13.10` to `9.13.11` (#8569) +- Remove duplicate `Open Here` context menu item upgrading to newer Preview release (#8496) +- Bump `NJsonSchema` from `9.13.9` to `9.13.10` (#8511) +- Bump `NJsonSchema` from `9.13.7` to `9.13.9` (#8498) +- Bump `NJsonSchema` from `9.13.4` to `9.13.7` (#8493) +- Bump `NJsonSchema` from `9.13.3` to `9.13.4` (#8462) +- Fix daily NuGet publishing (#8460) +- Bump `NJsonSchema` from `9.13.2` to `9.13.3` (#8457) +- Bump `Markdig.Signed` from `0.15.4` to `0.15.5` (#8444) + +### Documentation and Help Content +- Remove unused `AppVeyor` links from `README.md` (#8685) (Thanks @RDIL!) +- Update `README.md` (#8684) +- Update Package Management license to MIT (#8676) (Thanks @RDIL!) +- Create Support File (#8618) (Thanks @RDIL!) +- Update git clone URL (#8673) (Thanks @RDIL!) +- docs(contributing): add link check information (#8659) (Thanks @RDIL!) +- Update License and Third Party Notice (#8646) +- Update README, `metadata.json` and changelog for release `6.1.2` (#8658) +- Fix typo in `README.md` (#8642) (Thanks @MarkTiedemann!) +- Fix some typos in the README (#8623) (Thanks @RDIL!) +- Remove `en-us` from `docs.microsoft.com` URL (#8628) (Thanks @xtqqczze!) +- Update examples for hosting PSCore and remove old outdated examples (#8472) (Thanks @bergmeister!) +- Update the pull request template (#8624) (Thanks @RDIL!) +- Contributing guidelines: Remove references to Travis CI and AppVeyor (#8617) (Thanks @RDIL!) +- Update code coverage analysis document (#8543) (Thanks @xtqqczze!) +- Remove `en-us` from our doc links (#8602) +- Document `First-time-issue` and `Hackathon`/`Hacktoberfest` labels (#8575) +- Updated linux build link (#8579) (Thanks @jwmoss!) +- Update contributing guidelines doc to run spellchecking in English (#8473) (Thanks @RDIL!) +- Updating links to point to new VS Code docs (#8468) + ## v6.2.0-preview.3 - 2018-12-10 ### Breaking Changes @@ -1639,7 +1810,7 @@ To read more about this, check out [this blog post](https://blogs.msdn.microsoft * Add support for `Invoke-Item -Path `. (#4262) * Fix `ConvertTo-Html` output when using a single column header. (#4276) * Fix output of `Length` for `FileInfo` when using `Format-List`. (#4437) -* Fix an issue in implicit remoting where restricted sessions couldn't use `Get-FormatData –PowerShellVersion`. (#4222) +* Fix an issue in implicit remoting where restricted sessions couldn't use `Get-FormatData �PowerShellVersion`. (#4222) * Fix an issue where `Register-PSSessionConfiguration` fails if `SessionConfig` folder doesn't exist. (#4271) ### Installer updates